
Le pipeline fonctionne, mais il est lent et le job de build Docker échoue. Les jobs Python utilisent python:3.12, une image qui pèse plus de 900 Mo. Et le job docker-build utilise aussi une image Python — ce qui est absurde, puisqu’une image Python ne contient pas Docker. Dans ce lab, vous allez corriger ces deux problèmes en choisissant la bonne image pour chaque job.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Comprendre le rôle de l’image Docker dans un job GitLab CI/CD
- Choisir entre
python:3.12etpython:3.12-slimselon le contexte - Configurer Docker-in-Docker pour construire des images dans un pipeline
- Lire la taille des images et mesurer l’impact sur la durée du pipeline
Dans quel contexte ?
Section intitulée « Dans quel contexte ? »Chaque job GitLab CI tourne dans un conteneur Docker. Le runner télécharge l’image spécifiée, crée un conteneur, et exécute vos commandes dedans. Si l’image est lourde (900 Mo vs 150 Mo), chaque job perd du temps à la télécharger — surtout sur les runners qui ne mettent pas les images en cache entre les runs.
Situations réelles où ce lab vous aide :
- Votre pipeline prend 8 minutes alors que les tests eux-mêmes durent 30 secondes — la majeure partie du temps est dans le pull des images
- Un collègue a copié-collé
image: python:3.12partout sans réfléchir au choix - Le job de build Docker échoue avec
docker: command not found— l’image utilisée ne contient pas Docker - Vous voulez comparer les temps de pipeline avant et après optimisation des images
Prérequis
Section intitulée « Prérequis »- Lab 02 complété — ou partir directement de la branche
starter/lab-03 - Avoir lu Runners GitLab CI/CD (conseillé)
Point de départ
Section intitulée « Point de départ »-
Passez sur la branche de départ
Fenêtre de terminal cd pipeline-craftgit checkout starter/lab-03 -
Poussez pour déclencher le pipeline
Fenêtre de terminal git push origin starter/lab-03 -
Observez le résultat dans Build > Pipelines
Le pipeline démarre. Les jobs
ruff-lintetpytestpassent — lentement. Le jobdocker-buildéchoue. C’est ce que vous allez corriger.
Le problème
Section intitulée « Le problème »Regardez le .gitlab-ci.yml de la branche starter/lab-03 :
ruff-lint: stage: lint image: python:3.12 # ← 900+ Mo, lent à télécharger ...
pytest: stage: test image: python:3.12 # ← idem ...
docker-build: stage: build image: python:3.12 # ← ERREUR : Python ne contient pas Docker ! script: - docker build -t pipeline-craft:test .Il y a deux problèmes distincts.
Le premier est une question de performance : l’image python:3.12 est la version “complète” de Python, avec des compilateurs, des outils de développement système et des bibliothèques inutiles pour faire du lint ou lancer des tests. L’image python:3.12-slim est une version allégée qui contient exactement ce qu’il faut pour faire tourner Python — et rien de plus. Elle est environ 6 fois plus légère.
Le second est une erreur fonctionnelle : le job docker-build utilise image: python:3.12, une image qui contient Python et pip, mais pas la commande docker. Quand GitLab tente de lancer docker build, il obtient immédiatement sh: docker: command not found. Pour construire des images Docker dans un pipeline, il faut une image qui contient le client Docker — et un service qui fournit le daemon Docker.
L’exercice
Section intitulée « L’exercice »Corriger les images Python
Section intitulée « Corriger les images Python »-
Ouvrez
.gitlab-ci.ymldans votre éditeur -
Remplacez
python:3.12parpython:3.12-slimdans les jobsruff-lintetpytestruff-lint:stage: lintimage: python:3.12-slim # ← allégébefore_script:- pip install ruffscript:- ruff check app/ tests/pytest:stage: testimage: python:3.12-slim # ← allégébefore_script:- pip install -r requirements-dev.txtscript:- pytest -v -
Corrigez le job
docker-buildRemplacez entièrement le job
docker-build:docker-build:stage: buildimage: docker:27services:- docker:27-dindvariables:DOCKER_TLS_CERTDIR: "/certs"script:- docker build -t pipeline-craft:test .Voici ce que fait chaque ligne de configuration supplémentaire :
image: docker:27— cette image contient uniquement le client Docker (la commandedocker). Elle est très légère (~50 Mo) et n’a pas Python.services: - docker:27-dind— GitLab lance un conteneur annexe avec le daemon Docker (dockerd). C’est lui qui reçoit et exécute les commandesdocker build,docker push, etc.DOCKER_TLS_CERTDIR: "/certs"— le client Docker doit s’authentifier auprès du daemon via TLS. Cette variable indique où trouver les certificats que GitLab génère automatiquement.
Sans le service
dind, la commandedocker buildéchouerait avecCannot connect to the Docker daemon. Sans la variable TLS, la connexion échouerait pour une raison différente. Ces trois lignes forment un bloc indissociable.
Le fichier complet
Section intitulée « Le fichier complet »stages: - lint - test - build
ruff-lint: stage: lint image: python:3.12-slim before_script: - pip install ruff script: - ruff check app/ tests/
pytest: stage: test image: python:3.12-slim before_script: - pip install -r requirements-dev.txt script: - pytest -v
docker-build: stage: build image: docker:27 services: - docker:27-dind variables: DOCKER_TLS_CERTDIR: "/certs" script: - docker build -t pipeline-craft:test .Pousser et vérifier
Section intitulée « Pousser et vérifier »-
Committez et poussez
Fenêtre de terminal git add .gitlab-ci.ymlgit commit -m "ci: use slim images and fix docker-build with dind"git push origin starter/lab-03 -
Observez le pipeline dans Build > Pipelines
Les trois jobs doivent passer au vert. Regardez la durée de chaque job — les jobs Python sont plus rapides qu’avant grâce aux images slim.
Vérification
Section intitulée « Vérification »- Le job
ruff-lintutilisepython:3.12-slimet passe au vert - Le job
pytestutilisepython:3.12-slimet passe au vert - Le job
docker-buildutilisedocker:27+ servicedocker:27-dindet passe au vert - Plus d’erreur
docker: command not found
Ce qui a changé
Section intitulée « Ce qui a changé »ruff-lint: image: python:3.12 image: python:3.12-slim
pytest: image: python:3.12 image: python:3.12-slim
docker-build: image: python:3.12 script: - docker build -t pipeline-craft:test . image: docker:27 services: - docker:27-dind variables: DOCKER_TLS_CERTDIR: "/certs" script: - docker build -t pipeline-craft:test .Pièges fréquents
Section intitulée « Pièges fréquents »| Symptôme | Cause | Solution |
|---|---|---|
docker: command not found | Image sans Docker (ex : python:3.12) utilisée pour docker build | Utiliser image: docker:27 |
Cannot connect to the Docker daemon | Service docker:27-dind absent | Ajouter services: - docker:27-dind |
TLS handshake error | Variable DOCKER_TLS_CERTDIR manquante | Ajouter DOCKER_TLS_CERTDIR: "/certs" |
pip install échoue avec -slim | Le paquet nécessite un compilateur C absent des images slim | Utiliser l’image complète ou ajouter apt-get install -y gcc avant pip |
Pour aller plus loin
Section intitulée « Pour aller plus loin »- Explorez Docker Hub : toutes les images officielles expliquent la différence entre les variantes (
latest,slim,alpine,bullseye…). Pour Python, consultez hub.docker.com/_/python. - Comparez avec
solution/lab-03:git diff starter/lab-03..solution/lab-03montre exactement les corrections attendues. - Prochain level : dans le Lab 04, vous allez accélérer encore le pipeline en mettant les dépendances pip en cache pour éviter de les réinstaller à chaque run.
À retenir
Section intitulée « À retenir »- L’image Docker d’un job doit correspondre à ce que le job fait : un job Python utilise une image Python, un job de build Docker utilise une image Docker
- Les images
-slimsont 5–7x plus légères que les images complètes et suffisent dans la quasi-totalité des cas CI/CD - Docker-in-Docker nécessite trois éléments :
image: docker:27,services: - docker:27-dind, etDOCKER_TLS_CERTDIR: "/certs"— ces trois lignes forment un bloc indissociable - Le choix de l’image a un impact direct sur la durée du pipeline — chaque Mo téléchargé prend du temps