TP11 : GitLab CI/CD et runner auto-hébergé
Après Jenkins (TP9) et GitHub Actions (TP3, TP10), ce TP fait découvrir le troisième grand outil de CI/CD : GitLab CI/CD. La forge, la CI, le registre de conteneurs et les scanners de sécurité y sont intégrés dans un même produit. Vous exécutez le pipeline sur votre propre runner, installé sur la VM de lab, pour comprendre comment fonctionnent les runners auto-hébergés et comment les sécuriser.
Fichiers de départ :
gitlab-ci-starter.zip
1. Objectifs pédagogiques
À l’issue du TP, vous serez capable de :
- lire et écrire un
.gitlab-ci.yml:stages, jobs,needs,rules,cache,artifacts, variables ; - installer et enregistrer un GitLab Runner auto-hébergé (executor Docker) et expliquer son modèle pull ;
- utiliser les variables prédéfinies et les variables CI/CD protégées et masquées ;
- intégrer les templates de sécurité GitLab (SAST, Secret Detection) ;
- publier une image dans le registre de conteneurs GitLab ;
- comparer Jenkins, GitHub Actions et GitLab CI/CD sur des critères objectifs.
Les images de cette page sont des schémas explicatifs, pas des captures d’écran.
2. Environnement du TP
- Un compte gitlab.com (offre gratuite). GitLab peut demander une vérification d’identité pour utiliser ses runners partagés : ce TP n’en a pas besoin, puisque vous utilisez votre propre runner.
- VM de lab Ubuntu Server 26.04 avec Docker.
- Le projet
contact-apidu TP8, avec sonDockerfile, importé dans un nouveau projet GitLab (New project → Import project → Repository by URL, ougit remote add gitlab …puisgit push). - Settings → CI/CD → Runners : désactiver les instance runners du projet, afin que seuls vos runners exécutent les jobs.
| Terme | Signification |
|---|---|
| Pipeline | Ensemble des jobs déclenchés par un push, une merge request, un tag ou une planification. |
| Stage / Job | Étape logique / unité de travail exécutée par un runner dans un conteneur. |
| Runner | Agent qui interroge GitLab, récupère les jobs et les exécute (executor shell, Docker, Kubernetes…). |
| Tags | Étiquettes qui associent un job aux runners capables de l’exécuter. |
needs |
Dépendance explicite entre jobs : un job démarre dès que ses dépendances sont finies (graphe orienté). |
| Artefact / cache | Fichiers transmis aux jobs suivants (artefact) / réutilisés entre pipelines (cache). |
3. Partie 1 : Installer et enregistrer le runner
-
Installer GitLab Runner depuis le dépôt officiel :
curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh" | sudo bash sudo apt install -y gitlab-runner sudo usermod -aG docker gitlab-runner gitlab-runner --versionSi le dépôt ne propose pas encore de paquet pour Ubuntu 26.04, utilisez le paquet
nobleou le binaire officiel (/usr/local/bin/gitlab-runner). -
Dans le projet : Settings → CI/CD → Runners → New project runner, tag
lab, cocher Run untagged jobs (nécessaire aux templates de sécurité), puis copier le jetonglrt-…. -
Enregistrer le runner avec l’executor Docker :
sudo gitlab-runner register --non-interactive --url https://gitlab.com \ --token glrt-XXXXXXXX --executor docker --docker-image node:24-alpine --description lab-runner sudo gitlab-runner verify sudo systemctl status gitlab-runner -
Comparer le fichier
/etc/gitlab-runner/config.tomlavecrunner-config.toml.exampleet ajouter le montage du socket Docker. Lire l’avertissement : quel risque prend-on ? -
Le runner apparaît-il en vert dans GitLab ? Expliquer pourquoi aucun port n’a dû être ouvert sur la VM.
4. Partie 2 : Premier pipeline
- Copier
.gitlab-ci.ymlà la racine du projet, puis commiter et pousser. - Build → Pipelines : ouvrir le pipeline, consulter le graphe des jobs et les logs. Sur quel runner chaque job s’est-il exécuté ?
- Valider la syntaxe avec l’éditeur de pipeline (Build → Pipeline editor → Validate) et afficher la configuration fusionnée (Full configuration).
5. Partie 3 : Cache, artefacts, rules et registre
- Compléter les
TODOde la partie 3 :cachede.npm/aveckey: files: [package-lock.json];artifacts:node_modules/(1 h) et le rapport JUnit (reports: junit:,when: always) ;rules:build-imagesur les merge requests et la branche par défaut ;push-imageuniquement sur la branche par défaut ;docker loginavecCI_REGISTRY_USER/CI_REGISTRY_PASSWORD, puisdocker push "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA".
- Mesurer la durée du job
installavant et après le cache. - Ouvrir une merge request depuis une branche
feature/…: vérifier quepush-imagen’apparaît pas dans son pipeline et que l’onglet Tests affiche le rapport JUnit. - Après le merge, vérifier l’image dans Deploy → Container Registry.
- Créer une variable CI/CD
DEMO_TOKEN(Settings → CI/CD → Variables) masquée et protégée, l’utiliser dans un job (echo "longueur: ${#DEMO_TOKEN}") et observer :- qu’elle est masquée dans les logs ;
- qu’elle est absente des pipelines des branches non protégées.
6. Partie 4 : Sécurité intégrée
-
Décommenter l’
includedes templates SAST et Secret Detection, pousser, et observer les nouveaux jobs (semgrep-sast,secret_detection…). -
Télécharger les artefacts
gl-sast-report.jsonetgl-secret-detection-report.json, puis comparer avec Semgrep et Gitleaks du TP10 : sur quels moteurs s’appuie GitLab ?Dans l’offre gratuite, les rapports sont disponibles sous forme d’artefacts JSON. Le tableau de bord de vulnérabilités, le widget de merge request et le Dependency Scanning demandent l’offre Ultimate : c’est pourquoi le contrôle des dépendances est fait ici avec
npm audit. -
Ajouter un faux secret dans une branche et vérifier qu’il est détecté.
-
Settings → Repository → Protected branches : interdire le push direct sur
main. Settings → Merge requests : exiger un pipeline réussi avant le merge.
7. Partie 5 : Comparaison des trois outils
- Compléter le tableau à partir de votre expérience des TP9, TP10 et TP11 :
| Critère | Jenkins | GitHub Actions | GitLab CI/CD |
|---|---|---|---|
| Configuration | |||
| Runners / agents | |||
| Secrets | |||
| Sécurité intégrée | |||
| Maintenance | |||
| Intégration Git |
- Rédiger une recommandation argumentée (10 lignes) pour une PME qui démarre son usine logicielle.
Défi
- Remplacer le montage du socket Docker par une construction d’image sans privilège (BuildKit rootless, Buildah ou Kaniko) et retirer le socket du
config.toml.- Après le TP14, déployer un runner dans Kubernetes (chart Helm
gitlab/gitlab-runner, executor Kubernetes) dans un namespace dédié, avec un ServiceAccount limité : c’est le moindre privilège appliqué aux runners.
8. Livrables
Captures à déposer dans captures/ :
| Fichier | Contenu attendu |
|---|---|
runner-online.png |
Runner lab-runner en ligne dans GitLab et gitlab-runner verify |
pipeline-graph.png |
Graphe du pipeline avec les needs |
cache.png |
Durée du job install avant / après le cache |
mr-pipeline.png |
Pipeline de merge request sans push-image, onglet Tests |
container-registry.png |
Image :<short-sha> dans le registre GitLab |
security-reports.png |
Jobs SAST et Secret Detection, extrait des rapports |
Ainsi que le .gitlab-ci.yml final et le tableau comparatif. Jamais le jeton du runner.