
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.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Utiliser
$CI_REGISTRY_IMAGEet les identifiants CI injectés par GitLab - Publier une image avec un tag traçable (
$CI_COMMIT_SHORT_SHA) - Maintenir un tag
latestsans perdre la traçabilité - Vérifier la présence de l'image dans l'UI GitLab
Quel lab commencer ?
Section intitulée « Quel lab commencer ? »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.
Dans quel contexte ?
Section intitulée « Dans quel contexte ? »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.
Prérequis
Section intitulée « Prérequis »- Lab 08, Déclencher un pipeline terminé
- Avoir lu Registries GitLab
Point de départ
Section intitulée « Point de départ »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.
-
Passez sur la branche du lab
Fenêtre de terminal cd pipeline-craftgit checkout starter/lab-09 -
Vérifiez le job
docker-buildDans
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 avecdocker 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 problème
Section intitulée « Le problème »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
latestdu 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 -pplace le jeton dans les arguments du processus, visible enpset 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.
L'exercice
Section intitulée « L'exercice »Étape 1, À vous de durcir le job de publication
Section intitulée « Étape 1, À vous de durcir le job de publication »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.
-
Fusionnez les deux
docker builden un seul à double tag :- un tag immuable basé sur le SHA
- un tag
latest
-
Remplacez
docker login -ppar une authentification--password-stdin. -
Confirmez la logique de traçabilité : rollback possible avec le tag SHA.
👉 Vérifier votre solution (Étape 1)
1️⃣ Job docker-build avec double tag
Section intitulée « 1️⃣ Job docker-build avec double tag »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:latest2️⃣ Variables prédéfinies utilisées
Section intitulée « 2️⃣ Variables prédéfinies utilisées »| Variable | Valeur exemple |
|---|---|
$CI_REGISTRY | registry.gitlab.com |
$CI_REGISTRY_IMAGE | registry.gitlab.com/user/pipeline-craft |
$CI_REGISTRY_USER | gitlab-ci-token |
$CI_REGISTRY_PASSWORD | (token de session CI, injecté automatiquement) |
$CI_COMMIT_SHORT_SHA | a1b2c3d4 |
Le docker login avant docker push est obligatoire. GitLab injecte ces credentials automatiquement, pas besoin de les configurer manuellement.
Étape 2, À vous de déclencher et vérifier
Section intitulée « Étape 2, À vous de déclencher et vérifier »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.
-
Commitez puis poussez
Fenêtre de terminal git add .gitlab-ci.ymlgit commit -m "ci: publish image to gitlab container registry"git push origin starter/lab-09 -
Ouvrez Deploy > Container Registry
Vérifiez que les deux tags sont présents.
-
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)
1️⃣ Vérifier dans Container Registry
Section intitulée « 1️⃣ Vérifier dans Container Registry »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.
- Allez dans Deploy > Container Registry
- Vous devriez voir deux tags sur votre image :
a1b2c3d4(SHA court du commit)latest
- Cliquez sur un tag pour voir les métadonnées
2️⃣ Relier commit et image
Section intitulée « 2️⃣ Relier commit et image »Le tag SHA vous permet de retrouver le contexte exact :
git show a1b2c3d4En 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.
-
Vérifiez que votre projet est compatible packaging
-
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_BRANCHCe lab se concentre sur le registry d'images. La publication package complète (build + upload) arrive dans un lab dédié.
Le fichier complet
Section intitulée « Le fichier complet »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: manualVérification
Section intitulée « Vérification »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 loginpasse 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
Pièges fréquents
Section intitulée « Pièges fréquents »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é.
À retenir
Section intitulée « À retenir »- Une image non poussée est perdue à la fin du job
CI_REGISTRY_*simplifie l'authentification sécurisée- Le duo
SHA + latestcouvre traçabilité et usage courant - La publication registry est une étape clé vers un déploiement fiable