Aller au contenu
CI/CD & Automatisation medium

Lab 09, Publier dans le registry

14 min de lecture

logo gitlab

Depuis le Lab 04, votre pipeline pousse déjà l'image dans le Container Registry. Mais il le fait de façon naïve : le mot de passe passe en clair dans la commande, et l'image est construite deux fois pour ses deux tags. Ce lab ne découvre donc pas la publication, il la fiabilise : un seul build à double tag et une authentification qui n'expose pas le jeton.

  • Utiliser $CI_REGISTRY_IMAGE et les identifiants CI injectés par GitLab
  • Publier une image avec un tag traçable ($CI_COMMIT_SHORT_SHA)
  • Maintenir un tag latest sans perdre la traçabilité
  • Vérifier la présence de l'image dans l'UI GitLab

Ce lab est la suite du Lab 08. Si vous savez déjà déclencher un pipeline et lire les variables CI, vous pouvez commencer directement via starter/lab-09.

Un pipeline qui ne publie pas ses artefacts finaux est incomplet. En pratique, les équipes ont besoin d'une image versionnée pour :

  • déployer en staging puis production
  • rollback sur une version précise
  • reproduire un incident avec l'image exacte

Sans tag immuable, vous perdez la traçabilité. Sans docker login, le push échoue. Sans discipline de tag, vous déployez au hasard.

La branche starter/lab-09 contient déjà un job docker-build qui pousse l'image dans le registry : le registre a été introduit au Lab 04. Votre travail ne consiste donc pas à écrire un Dockerfile ni à découvrir le push, mais à corriger deux défauts de ce job qui marche. Avant de modifier quoi que ce soit, ouvrez le .gitlab-ci.yml et repérez le job docker-build : c'est le seul que vous allez toucher dans les deux premières étapes.

  1. Passez sur la branche du lab

    Fenêtre de terminal
    cd pipeline-craft
    git checkout starter/lab-09
  2. Vérifiez le job docker-build

    Dans starter/lab-09, ce job pousse déjà l'image, mais avec deux défauts : il construit l'image deux fois (une par tag), et il s'authentifie avec docker login -p "$CI_REGISTRY_PASSWORD", ce qui expose le jeton dans les arguments du processus. Ce sont ces deux points que vous allez corriger.

Le job existant fonctionne, mais deux choses sont à durcir :

  • le double build : construire l'image une fois par tag gaspille du temps et risque de faire diverger latest du tag SHA si le build n'est pas déterministe. Un seul build à double tag garantit un digest commun.
  • le mot de passe en clair : docker login -p place le jeton dans les arguments du processus, visible en ps et dans les traces du job.

L'objectif reste de pouvoir dire précisément : « la version en prod correspond à ce commit », mais sans exposer le jeton ni multiplier les constructions.

Le job pousse déjà l'image avec les variables prédéfinies de GitLab (adresse du registry, chemin de l'image, identifiant, jeton de session), donc rien à écrire en dur. Ce que vous corrigez, c'est comment il construit et s'authentifie. Si vous vous surprenez à créer une variable de projet pour stocker un mot de passe de registry, c'est le signe que vous passez à côté du mécanisme.

  1. Fusionnez les deux docker build en un seul à double tag :

    • un tag immuable basé sur le SHA
    • un tag latest
  2. Remplacez docker login -p par une authentification --password-stdin.

  3. Confirmez la logique de traçabilité : rollback possible avec le tag SHA.

👉 Vérifier votre solution (Étape 1)

Deux points méritent votre attention dans ce job. L'ordre d'abord : le docker login doit précéder les docker push, mais peut suivre les docker build puisque la construction ne touche pas au registry. La façon de passer le mot de passe ensuite : il arrive par stdin et non par l'option -p. Un docker login -p "$CI_REGISTRY_PASSWORD" place le jeton dans les arguments du processus, donc dans la sortie de ps et dans les traces du job si le shell tourne en mode verbeux. La documentation GitLab elle-même utilise la forme --password-stdin.

docker-build:
stage: build
image: docker:27@sha256:aa3df78ecf320f5fafdce71c659f1629e96e9de0968305fe1de670e0ca9176ce
services:
- docker:27-dind
variables:
DOCKER_TLS_CERTDIR: "/certs"
script:
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA -t $CI_REGISTRY_IMAGE:latest .
- echo "$CI_REGISTRY_PASSWORD" | docker login $CI_REGISTRY -u $CI_REGISTRY_USER --password-stdin
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
- docker push $CI_REGISTRY_IMAGE:latest
VariableValeur exemple
$CI_REGISTRYregistry.gitlab.com
$CI_REGISTRY_IMAGEregistry.gitlab.com/user/pipeline-craft
$CI_REGISTRY_USERgitlab-ci-token
$CI_REGISTRY_PASSWORD(token de session CI, injecté automatiquement)
$CI_COMMIT_SHORT_SHAa1b2c3d4

Le docker login avant docker push est obligatoire. GitLab injecte ces credentials automatiquement, pas besoin de les configurer manuellement.

Un pipeline vert ne prouve pas que la publication a fonctionné : un docker push peut réussir sur un tag et échouer sur l'autre sans faire tomber le job si le script est mal écrit. La vérification se fait donc dans le registry, pas dans les traces. Vous cherchez deux entrées, la date de push et la taille de l'image ; deux tags qui pointent sur le même digest confirment qu'ils proviennent bien du même build.

  1. Commitez puis poussez

    Fenêtre de terminal
    git add .gitlab-ci.yml
    git commit -m "ci: publish image to gitlab container registry"
    git push origin starter/lab-09
  2. Ouvrez Deploy > Container Registry

    Vérifiez que les deux tags sont présents.

  3. Notez le lien entre image et commit

    Le tag SHA vous permet de retrouver la source exacte de l'image.

👉 Vérifier votre solution (Étape 2)

L'interface liste les dépôts d'images du projet, un par ligne. En ouvrant celui de pipeline-craft, vous obtenez la liste des tags avec leur digest sha256. C'est ce digest qui compte : si latest et le tag SHA affichent la même valeur, ils désignent le même contenu et votre publication est cohérente. S'ils diffèrent, c'est que les deux tags proviennent de deux constructions distinctes, et le latest ne représente plus le commit que vous croyez.

  1. Allez dans Deploy > Container Registry
  2. Vous devriez voir deux tags sur votre image :
    • a1b2c3d4 (SHA court du commit)
    • latest
  3. Cliquez sur un tag pour voir les métadonnées

Le tag SHA vous permet de retrouver le contexte exact :

Fenêtre de terminal
git show a1b2c3d4

En cas d'incident en production, vous pouvez déployer exactement l'image correspondant au commit connu comme stable.

Étape 3, À vous de préparer la publication package (option)

Section intitulée « Étape 3, À vous de préparer la publication package (option) »

GitLab héberge deux registres distincts : le Container Registry pour les images, et le Package Registry pour les artefacts de langage (paquets Python, npm, Maven, conteneurs Helm). Cette étape ne publie rien, elle pose la place du futur job dans le pipeline. L'intérêt de le déclarer maintenant, même vide, est de fixer le stage et la règle de déclenchement avant d'écrire la logique de packaging : un job de publication qui tournerait sur chaque branche de fonctionnalité polluerait le registre de versions jetables.

  1. Vérifiez que votre projet est compatible packaging

  2. Préparez un job dédié pour un lab ultérieur

    Ce lab se concentre sur le registry d'images. La publication package pourra être ajoutée ensuite avec twine.

👉 Vérifier votre solution (Étape 3)

1️⃣ Extension vers Package Registry (référence)

Section intitulée « 1️⃣ Extension vers Package Registry (référence) »

Dans solution/lab-09, le lab prépare un squelette minimal pour la publication package :

publish-package:
stage: build
image: python:3.12-slim@sha256:57cd7c3a7a273101a6485ba99423ee568157882804b1124b4dd04266317710de
script:
- echo "Would publish package to GitLab Package Registry"
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

Ce lab se concentre sur le registry d'images. La publication package complète (build + upload) arrive dans un lab dédié.

Le fichier ci-dessous cumule tout ce qui a été construit depuis le Lab 01 : lint, tests, build d'image et déploiements. Comparez-le au vôtre plutôt que de le copier tel quel, c'est la seule façon de repérer une différence d'indentation ou une règle oubliée. Notez au passage que deploy-production porte when: manual : le pipeline s'arrête et attend un clic, ce qui est le minimum sur un job qui touche la production.

📄 Voir le fichier .gitlab-ci.yml complet
stages:
- lint
- test
- build
- deploy
workflow:
rules:
- if: $CI_PIPELINE_SOURCE == "push"
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
- if: $CI_COMMIT_TAG
- if: $CI_PIPELINE_SOURCE == "schedule"
- if: $CI_PIPELINE_SOURCE == "trigger"
- if: $CI_PIPELINE_SOURCE == "api"
variables:
PIP_CACHE_DIR: "$CI_PROJECT_DIR/.pip-cache"
ruff-lint:
stage: lint
image: python:3.12-slim@sha256:57cd7c3a7a273101a6485ba99423ee568157882804b1124b4dd04266317710de
cache:
key:
files:
- requirements-dev.txt
paths:
- .pip-cache/
policy: pull
before_script:
- pip install ruff
script:
- ruff check app/ tests/
pytest:
stage: test
image: python:3.12-slim@sha256:57cd7c3a7a273101a6485ba99423ee568157882804b1124b4dd04266317710de
cache:
key:
files:
- requirements-dev.txt
paths:
- .pip-cache/
before_script:
- pip install -r requirements-dev.txt
script:
- 'echo "Pipeline source: $CI_PIPELINE_SOURCE"'
- pytest -v --junitxml=report.xml
artifacts:
when: always
paths:
- report.xml
reports:
junit: report.xml
expire_in: 7 days
nightly-regression:
stage: test
image: python:3.12-slim@sha256:57cd7c3a7a273101a6485ba99423ee568157882804b1124b4dd04266317710de
cache:
key:
files:
- requirements-dev.txt
paths:
- .pip-cache/
before_script:
- pip install -r requirements-dev.txt
script:
- echo "Nightly run on source=$CI_PIPELINE_SOURCE"
- pytest -v
rules:
- if: $CI_PIPELINE_SOURCE == "schedule"
docker-build:
stage: build
image: docker:27@sha256:aa3df78ecf320f5fafdce71c659f1629e96e9de0968305fe1de670e0ca9176ce
services:
- docker:27-dind
variables:
DOCKER_TLS_CERTDIR: "/certs"
script:
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA -t $CI_REGISTRY_IMAGE:latest .
- echo "$CI_REGISTRY_PASSWORD" | docker login $CI_REGISTRY -u $CI_REGISTRY_USER --password-stdin
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
- docker push $CI_REGISTRY_IMAGE:latest
publish-package:
stage: build
image: python:3.12-slim@sha256:57cd7c3a7a273101a6485ba99423ee568157882804b1124b4dd04266317710de
script:
- echo "Would publish package to GitLab Package Registry"
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
deploy-staging:
stage: deploy
image: alpine:3.20@sha256:d9e853e87e55526f6b2917df91a2115c36dd7c696a35be12163d44e6e2a4b6bc
script:
- echo "Deploying $CI_COMMIT_SHORT_SHA to staging..."
- ./scripts/deploy-demo.sh staging
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
deploy-production:
stage: deploy
image: alpine:3.20@sha256:d9e853e87e55526f6b2917df91a2115c36dd7c696a35be12163d44e6e2a4b6bc
script:
- echo "Deploying $CI_COMMIT_SHORT_SHA to production..."
- ./scripts/deploy-demo.sh production
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
when: manual

Le lab est validé quand vous pouvez remonter d'une image vers son commit sans consulter les traces du pipeline. Les trois premières cases se lisent dans le job et dans l'interface ; la quatrième est celle qui compte vraiment, car c'est elle que vous rejouerez le jour d'un incident en production.

  • docker login passe sans erreur
  • Le push des deux tags réussit
  • Les tags sont visibles dans Container Registry
  • Vous pouvez relier un tag SHA à un commit Git

Le tag latest seul est insuffisant pour investiguer un incident. Utilisez toujours un tag immuable en parallèle.

Un autre piège fréquent est de supposer que les credentials registry doivent être ajoutés à la main. Dans GitLab CI, ils sont déjà injectés via les variables prédéfinies si le registry est activé.

  • Une image non poussée est perdue à la fin du job
  • CI_REGISTRY_* simplifie l'authentification sécurisée
  • Le duo SHA + latest couvre traçabilité et usage courant
  • La publication registry est une étape clé vers un déploiement fiable

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracking. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn