Build and Image Publish¶
Placeholder names used on this page¶
ENTITY_NAMESPACE=<entity-namespace> # ex: france-titres
APP_SLUG=<app-slug> # ex: hello-world
REGISTRY_HOST=<registry-host> # ex: tools.playground.france-identite.gouv.fr
IMAGE_REPO="$REGISTRY_HOST/$ENTITY_NAMESPACE/$APP_SLUG"
IMAGE_TAG=<tag> # current CI default: CI_COMMIT_SHORT_SHA
Today, these placeholders map to:
| Placeholder | Actual variable used |
|---|---|
IMAGE_REPO |
${HARBOR_HOST}/${HARBOR_PROJECT}/${CI_PROJECT_NAME} |
IMAGE_TAG |
${CI_COMMIT_SHORT_SHA} |
How the image is built¶
The build happens in two stages:
- Build stage (
node:21-alpine) โ installs dependencies withnpm ci, then runsnpm run build - Runtime stage (
nginxinc/nginx-unprivileged:alpine) โ copies the built/app/distfolder into Nginx's html root and serves it on port80
How the image is tagged and pushed¶
CI uses Kaniko to build and push the image. Kaniko builds Docker images without needing a Docker daemon, which is why it's used inside CI runners:
mkdir -p /kaniko/.docker
echo "{\"auths\":{\"${HARBOR_HOST}\":{\"auth\":\"$(echo -n ${HARBOR_USERNAME}:${HARBOR_PASSWORD} | base64 -w 0)\"}}}" > /kaniko/.docker/config.json
/kaniko/executor \
--context "${CI_PROJECT_DIR}" \
--dockerfile "Dockerfile" \
--destination "${HARBOR_HOST}/${HARBOR_PROJECT}/${CI_PROJECT_NAME}:${CI_COMMIT_SHORT_SHA}"
What this means in practice:
- Every build publishes a new image tagged with the commit's short SHA
- These tags never change once published โ they're immutable
- There's no
latesttag here โ each deployment should reference an exact commit tag
Variables and secrets you need¶
| Variable | Required | Where it comes from | What it's for |
|---|---|---|---|
HARBOR_HOST |
Yes | GitLab CI variable | The registry's hostname |
HARBOR_PROJECT |
Yes | GitLab CI variable | The registry namespace/project (maps to ENTITY_NAMESPACE) |
HARBOR_USERNAME |
Yes | GitLab CI variable (secret) | Registry login username |
HARBOR_PASSWORD |
Yes | GitLab CI variable (secret) | Registry login password |
CI_PROJECT_NAME |
Yes | Provided automatically by GitLab | Used as part of the image name |
CI_COMMIT_SHORT_SHA |
Yes | Provided automatically by GitLab | Used as the image tag |
HARBOR_* variables aren't stored in the repository โ they're configured separately in GitLab's CI/CD settings.
Troubleshooting¶
"Cannot locate Dockerfile"¶
Why it happens: Kaniko expects your Dockerfile to sit at the repository root.
How to fix it:
- Check that Dockerfile exists at the root of the repo
- Or update the --dockerfile argument in .gitlab-ci.yml to point to the right path
"unauthorized" when pushing¶
Why it happens: The Harbor credentials are missing or invalid, or HARBOR_HOST/HARBOR_PROJECT are wrong.
How to fix it: Double-check these values and their permissions in GitLab's CI/CD variable settings.
The image runs, but the service isn't reachable on the expected port¶
Why it happens: The port your app listens on inside the container doesn't match the port the Kubernetes Service expects.
How to fix it: Check that the port is consistent across the Dockerfile, the Service, and the Deployment.