CI/CD avec Docker
Automatiser le déploiement d'applications avec des conteneurs
Il est recommandé de consulter la documentation officielle de Docker et celle de GitHub Actions pour des informations à jour.
Notions théoriques
Le CI/CD (Intégration Continue / Déploiement Continu) est un ensemble de pratiques visant à automatiser les étapes de développement, de test et de déploiement d'une application.
Docker permet de faciliter cette automatisation grâce à la conteneurisation des applications.
Intégration continue (CI)
L'intégration continue consiste à tester automatiquement le code à chaque modification. L'objectif est de détecter rapidement les erreurs et de garantir que l'application reste fonctionnelle au fil des versions.
Les étapes typiques de la CI sont :
- Récupérer le code depuis un dépôt (par exemple sur GitHub)
- Installer les dépendances
- Lancer les tests automatiques
- Construire une image Docker
Déploiement continu (CD)
Le déploiement continu consiste à livrer automatiquement une nouvelle version de l'application après validation. Cela peut inclure :
- Pousser l'image Docker sur un registre (Docker Hub, GitHub Container Registry…)
- Déployer l'image sur un serveur de production ou de test
Pourquoi utiliser Docker dans un pipeline CI/CD
Docker permet de :
- Garantir que l’environnement d’exécution est identique en local, en test et en production
- Automatiser la construction et le déploiement des applications
- Réduire les erreurs liées aux différences de configuration
Outils courants
- GitHub Actions : permet de définir des workflows d’automatisation directement dans un dépôt GitHub
- Docker Hub : registre d’images Docker
- GitLab CI/CD : alternative à GitHub Actions, intégrée à GitLab
- Travis CI, CircleCI, Jenkins : autres outils CI/CD
Fichier de configuration .github/workflows/
Un workflow GitHub Actions est défini dans un fichier YAML. Il contient :
- Des déclencheurs (
on: push,on: pull_request, etc.) - Des jobs (unités d'exécution)
- Des steps (étapes à exécuter dans chaque job)
Exemple de structure :
name: CI
on:
push:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Build Docker image
run: docker build -t mon-image .
Bonnes pratiques
- Versionner les images Docker (éviter le tag
latest) - Utiliser des secrets pour les identifiants (Docker Hub, SSH, etc.)
- Scanner les images Docker pour détecter les vulnérabilités
- Nettoyer les ressources inutiles après le build
- Utiliser des images légères (ex :
python:3.11-slim)

Exemple pratique
Il est possible de configurer un pipeline CI/CD avec GitHub Actions pour construire une image Docker à chaque push sur la branche main, puis la publier sur Docker Hub.
Étapes
- Créer un projet contenant un fichier
app.py:
print("Application CI/CD avec Docker")
- Créer un
Dockerfile:
FROM python:3.11-slim
WORKDIR /app
COPY app.py .
CMD ["python", "app.py"]
- Créer un fichier
.github/workflows/docker.yml:
name: Build and Push Docker Image
on:
push:
branches:
- main
jobs:
docker:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Login to Docker Hub
run: echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u "${{ secrets.DOCKER_USERNAME }}" --password-stdin
- name: Build image
run: docker build -t mon-utilisateur/mon-image:latest .
- name: Push image
run: docker push mon-utilisateur/mon-image:latest
-
Ajouter les secrets
DOCKER_USERNAMEetDOCKER_PASSWORDdans les paramètres du dépôt GitHub -
Pousser le projet sur GitHub
À chaque git push sur main, GitHub Actions construit et publie l’image sur Docker Hub.
Test de mémorisation/compréhension
TP pour réfléchir et résoudre des problèmes
Créer un pipeline CI/CD pour une API Flask avec Docker et GitHub Actions
Ce TP consiste à créer une API Web simple avec Flask, à la conteneuriser avec Docker, puis à configurer un pipeline CI/CD avec GitHub Actions pour construire et publier l’image Docker sur Docker Hub à chaque modification du code.
Étape 1 — Créer une API Flask minimaliste
Créer un projet contenant une API Flask avec un seul point d’entrée (/ping) qui retourne un message simple au format JSON.
📌 Une solution
Étape 2 — Écrire un Dockerfile pour conteneuriser l’API
Créer un Dockerfile qui utilise une image Python légère et expose le port 5000.
📌 Une solution
Étape 3 — Tester l’image Docker localement
Construire l’image Docker et lancer le conteneur pour vérifier que l’API fonctionne.
📌 Une solution
Étape 4 — Initialiser un dépôt Git et pousser le projet sur GitHub
Créer un dépôt GitHub et y pousser le code source du projet.
📌 Une solution
Étape 5 — Créer un fichier .github/workflows/docker.yml
Créer un fichier de workflow GitHub Actions pour construire l’image Docker à chaque push sur main et la publier sur Docker Hub.
📌 Une solution
Étape 6 — Ajouter les secrets dans GitHub
Ajouter les identifiants Docker Hub dans les paramètres du dépôt GitHub.
📌 Une solution
Étape 7 — Vérifier l’exécution du pipeline
Effectuer un git push pour déclencher le pipeline et vérifier que l’image Docker est publiée sur Docker Hub.
📌 Une solution
Étape 8 — Lancer l’image depuis Docker Hub
Tester l’image publiée en la téléchargeant depuis Docker Hub et en la lançant localement.
📌 Une solution
Étape 9 — Ajouter un tag de version à l’image Docker
Modifier le workflow pour ajouter un tag versionné basé sur le numéro de commit court ou une version définie.
📌 Une solution
Étape 10 — Ajouter un test automatique dans le pipeline
Ajouter une étape dans le workflow pour vérifier que le port 5000 est bien exposé après le build.