Pipelines CI/CD - Docker
Contactez-moi- Docker
- CI/CD
- GitLab CI
- GitHub Actions
- Trivy
- Playwright
- OWASP ZAP
Un pipeline CI/CD automatise le passage du code source à une application déployée : compilation, tests, packaging, publication puis déploiement, sans intervention manuelle répétée. Docker permet d’empaqueter une application et ses dépendances dans une image reproductible, exécutée de façon identique en local, en CI et en production, ce qui élimine une grande partie des “ça marche sur ma machine”.
Historique
La pratique d’intégration continue est formalisée dans les années 2000 (popularisée notamment par Martin Fowler), avec des outils comme Jenkins (2011, fork du projet Hudson) pour l’automatiser. Docker est lancé en 2013 par la société dotCloud, en s’appuyant sur les mécanismes de conteneurisation déjà présents dans le noyau Linux (namespaces, cgroups), popularisés jusque-là par LXC. Son adoption massive a ensuite poussé GitLab CI (2015) et GitHub Actions (2019) à intégrer nativement l’exécution de jobs en conteneurs.
Avantages des versions récentes
- BuildKit : moteur de build Docker moderne, parallélisation des étapes et cache plus fin, builds sensiblement plus rapides.
- Builds multi-stage généralisés : images finales plus légères en séparant étape de compilation et image d’exécution.
- Compose v2 : intégré au CLI Docker, syntaxe simplifiée pour orchestrer plusieurs services en local ou en CI.
- Sécurité intégrée aux pipelines : scan de vulnérabilités et génération de SBOM directement dans les workflows GitLab CI / GitHub Actions.
Exemple : le pipeline GitLab CI des comparateurs de prix
Le front Angular SSR du réseau de comparateurs est construit, contrôlé et empaqueté par un pipeline GitLab CI en neuf étapes. Principe : plus un changement s’approche de la production, plus il doit franchir de contrôles.
Les étapes, une par une :
- Déclenchement : le pipeline démarre sur chaque merge request, branche et tag, avec une règle qui évite les pipelines en double quand une branche a déjà une merge request ouverte.
- Install :
npm cià partir du fichier de verrouillage, avec un cache indexé sur l’empreinte depackage-lock.json. Tant que les dépendances ne changent pas, elles ne sont pas retéléchargées. - Lint : ESLint et Semgrep (règles générales, JavaScript et TypeScript) analysent le code source. Ces jobs signalent sans bloquer : le rapport sert à progresser, pas à arrêter une livraison pour un avertissement.
- Tests unitaires : Karma et Jasmine dans un Chrome headless. La couverture (format Cobertura) et le rapport JUnit remontent dans GitLab, directement visibles sur la merge request.
- Tests E2E : Playwright, dans l’image officielle, lance l’application puis déroule les parcours utilisateur sur un vrai navigateur. Les rapports sont conservés 30 jours.
- Sécurité : plusieurs analyses complémentaires, en parallèle.
- Trivy sur les dépendances et sur les secrets : bloquants. Une vulnérabilité haute ou critique, ou un secret détecté, arrête le pipeline.
- Trivy sur la configuration (mauvaises pratiques d’infrastructure) et scan complet avec rapport HTML sur la branche principale et les tags.
- Gitleaks sur tout l’historique Git, et
npm audit, en complément. - Un scan Trivy hebdomadaire planifié détecte les nouvelles vulnérabilités publiées sur du code qui n’a pas changé.
- Build : Angular en mode SSR. Le build de développement sert les merge requests et la branche
develop. Le build de production est réservé à la branche principale et aux tags, et exige que les tests unitaires et les scans Trivy des dépendances et des secrets soient passés. - Image Docker : l’image n’est construite que depuis le build déjà généré, sans recompilation. Elle est légère (Node en version slim), exécutée par un utilisateur non privilégié, avec
nodeen processus principal pour que les signaux d’arrêt soient bien transmis. Elle est publiée dans le registre GitLab sous deux étiquettes : le hash court du commit, qui permet de revenir à une version précise, etlatest. - Déploiement et DAST : le déploiement est un job manuel (staging depuis
develop, production depuis la branche principale ou un tag), soumis à la réussite des contrôles précédents. Un scan OWASP ZAP peut ensuite attaquer le staging pour détecter des failles que l’analyse statique ne voit pas.
Quelques choix structurent le pipeline :
- Un graphe de dépendances (
needs) plutôt qu’un simple enchaînement par étape : un job démarre dès que ses prérequis sont terminés, sans attendre le reste de l’étape. - Bloquant ou informatif : ce qui protège la production (Trivy, tests unitaires) bloque ; ce qui éclaire (lint, E2E, audit) informe.
- Variables CI/CD masquées : le pipeline attend l’accès à l’API du back-office dans des variables GitLab masquées, et s’arrête immédiatement si elles sont absentes.
- Rapports publiés : couverture, tests E2E et rapports de sécurité sont regroupés sur une page GitLab Pages.
- Contrôle du pipeline lui-même : un composant (Plumber) vérifie la conformité de la configuration CI.
Mon expertise
J’ai mis en place le pipeline GitLab CI du front des comparateurs de prix, qui couvre toute la chaîne :
- tests unitaires (Karma, Jasmine) et de bout en bout (Playwright) ;
- sécurité : Trivy sur les dépendances et les secrets (bloquant avant la production), Gitleaks,
npm auditet un scan hebdomadaire planifié ; - qualité : ESLint et Semgrep ;
- image Docker légère, publiée dans le registre GitLab sous le hash du commit ;
- déploiement soumis à validation manuelle, et scan OWASP ZAP du staging.