Skip to content

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:

  1. Build stage (node:21-alpine) โ€” installs dependencies with npm ci, then runs npm run build
  2. Runtime stage (nginxinc/nginx-unprivileged:alpine) โ€” copies the built /app/dist folder into Nginx's html root and serves it on port 80

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 latest tag 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.


Sources