E-NO
DevOps 10 min de lecture

Automatisation CI/CD avec Docker Compose : exemples pratiques

calendar_today Publié : 2026-11-04
update Dernière mise à jour : 2026-11-04
analytics Efficacité SEO : 100%
Illustration du guide technique pour « Automatisation CI/CD avec Docker Compose : exemples pratiques ».

Introduction

Automatiser les flux de travail Docker Compose dans les pipelines CI/CD peut améliorer considérablement la cohérence des déploiements et réduire les erreurs manuelles. Pourtant, de nombreuses équipes peinent à intégrer en toute sécurité des applications multi-conteneurs dans des pipelines automatisés. Ce guide pratique présente un exemple complet : de l'inventaire des versions et de l'environnement, à la configuration sécurisée, la vérification, la gestion des échecs et une checklist opérationnelle. Vous apprendrez à construire un pipeline qui valide votre fichier Compose, construit des images avec des identifiants uniques, exécute des tests, promeut à travers les étapes et revient en arrière en toute sécurité en cas de problème. En adoptant ces pratiques, votre processus de déploiement devient reproductible, auditable et moins sujet aux erreurs.

Nous utiliserons une pile applicative web représentative composée d'un service web Node.js, d'une base de données PostgreSQL et d'un cache Redis, définie dans un fichier docker-compose.yml. Chaque commande est montrée telle qu'elle apparaîtrait dans un script de pipeline CI/CD, avec les sorties attendues et les cas d'échec expliqués.

Inventaire des versions et de l'environnement

Avant d'automatiser quoi que ce soit, documentez les versions exactes et la topologie que vous utiliserez. Cela réduit les surprises causées par les différences entre le développement local et les environnements CI/CD. Pour ce guide, nous supposons :

  • Docker Engine 24.0 ou ultérieur
  • Plugin Docker Compose v2.20 ou ultérieur
  • Git pour le contrôle de source
  • Une plateforme CI/CD qui prend en charge l'exécution de commandes shell (par exemple, GitHub Actions, GitLab CI, Jenkins)
  • Un hôte cible (par exemple, une VM ou un serveur bare metal) avec accès SSH, ou un contexte Docker local pour les tests

Vérifiez vos versions locales avec :

docker --version
# Docker version 24.0.7, build afdd53b

docker compose version
# Docker Compose version v2.21.0

Si votre exécuteur CI utilise une version différente, incluez la sortie de docker compose version dans les journaux du pipeline pour chaque exécution. Figez les versions de Docker et Compose dans votre configuration CI pour éviter un comportement inattendu. Par exemple, dans GitHub Actions, vous pouvez installer des versions spécifiques :

- name: Install Docker Compose
  run: |
    sudo curl -L "https://github.com/docker/compose/releases/download/v2.21.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
    sudo chmod +x /usr/local/bin/docker-compose

Votre topologie applicative peut être un simple service web avec une base de données et un cache, définie dans un fichier docker-compose.yml comme celui-ci :

services:
  web:
    build: .
    image: myapp:${TAG:-latest}
    ports:
      - "80:80"
    depends_on:
      - db
      - redis
  db:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD: ${DB_PASSWORD}
    volumes:
      - db-data:/var/lib/postgresql/data
  redis:
    image: redis:7
volumes:
  db-data:

Assurez-vous que tous les services sont conteneurisés et que le fichier Compose fonctionne localement avant de passer au CI/CD. Exécutez docker compose up -d sur votre machine locale et testez l'application de bout en bout. Le premier pilote utile doit être étroit, mesurable et facile à inspecter localement avant le déploiement. Par exemple, commencez par un seul service qui exécute un contrôle de santé et renvoie une réponse prévisible. Une fois que cela fonctionne, ajoutez la base de données et le cache.

Question rapide 1 sur 2

Selon le passage sur les environnements de test automatisés, quelle commande peut être utilisée pour détruire un environnement de test isolé créé avec Compose après l'exécution des tests ?

Le passage montre la séquence `docker compose up -d`, `./run_tests`, puis `docker compose down` pour détruire l'environnement de test isolé.

Chemin de configuration sécurisé

La sécurité dans le CI/CD pour Docker Compose vient de la réalisation de petits changements ciblés et de la validation de chaque étape. Évitez d'introduire une orchestration complexe au début. Adoptez plutôt un pipeline qui :

  • Lint et valide le fichier Compose.
  • Construit des images avec un identifiant unique (par exemple, le SHA du commit).
  • Exécute des tests d'intégration dans un environnement Compose dédié.
  • Déploie vers la préproduction, vérifie la santé, puis promeut vers la production.
  • Conserve les images précédentes pour un retour en arrière instantané.

Utilisez des fichiers de surcharge spécifiques à l'environnement pour éviter de modifier le fichier Compose de base pour chaque environnement. Par exemple, votre docker-compose.yml de base peut définir le service web avec une étiquette par défaut et le port 80. Pour la production, vous surchargez le port et ajoutez des limites de ressources :

# docker-compose.yml de base
services:
  web:
    image: myapp:${TAG:-latest}
    ports:
      - "80:80"
  db:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD: ${DB_PASSWORD}

# docker-compose.prod.yml (surcharge)
services:
  web:
    image: myapp:${TAG}
    ports:
      - "443:443"
    deploy:
      resources:
        limits:
          cpus: '0.5'
          memory: 512M

Dans votre pipeline, définissez TAG sur le SHA du commit et exécutez :

docker compose -f docker-compose.yml -f docker-compose.prod.yml config

La sortie attendue est le YAML fusionné avec les variables substituées, sans erreurs. Testez la substitution de variables avec un essai à sec :

TAG=abc123 docker compose config --quiet
# Aucune sortie signifie succès

Si le fichier Compose est invalide, docker compose config sort avec un statut non nul et affiche une erreur comme :

services.web.ports.0 must be a string

Attrapez cela dans votre script CI et faites échouer la construction.

Exemple de pipeline CI/CD avec GitHub Actions

Voici un workflow GitHub Actions complet qui construit, teste et promeut une application Docker Compose. Il est annoté avec des explications.

name: Docker Compose CI/CD

on:
  push:
    branches: [ main ]

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Set up Docker
        run: |
          docker --version
          docker compose version

      - name: Set image tag
        run: echo "TAG=${GITHUB_SHA::8}" >> $GITHUB_ENV

      - name: Validate Compose file
        run: docker compose config --quiet

      - name: Build images
        run: docker compose build

      - name: Run tests
        run: docker compose run --rm web npm test

      - name: Push images to registry
        run: |
          echo ${{ secrets.DOCKER_PASSWORD }} | docker login -u ${{ secrets.DOCKER_USERNAME }} --password-stdin
          docker compose push

      - name: Deploy to staging
        run: |
          ssh staging "TAG=$TAG docker compose -f docker-compose.yml -f docker-compose.staging.yml up -d"

      - name: Verify staging
        run: |
          sleep 10
          curl -fsS http://staging/health

      - name: Promote to production
        run: |
          ssh production "TAG=$TAG docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d"

      - name: Verify production
        run: |
          sleep 10
          curl -fsS http://production/health

Ce workflow utilise SSH pour exécuter les commandes de déploiement sur les hôtes de préproduction et de production. Vous pouvez également utiliser des contextes Docker ou un démon Docker distant pour une approche plus rationalisée, mais SSH est simple et fonctionne sur la plupart des plateformes.

Vérification et diagnostics

La vérification automatisée est critique. Après le déploiement, exécutez des tests de fumée contre les services en cours d'exécution. Pour un service web, utilisez curl pour vérifier les points de terminaison de santé :

curl -fsS http://localhost/health
# {"status":"ok"}

Si le point de terminaison renvoie un code non-2xx ou échoue à se connecter, le pipeline doit marquer le déploiement comme échoué. Utilisez docker compose ps pour inspecter les états des services :

docker compose ps
# NAME                COMMAND                  SERVICE   STATUS    PORTS
# myapp-web-1         "/docker-entrypoint...."  web       running   0.0.0.0:80->80/tcp
# myapp-db-1          "docker-entrypoint.s..."  db        running   5432/tcp
# myapp-redis-1       "docker-entrypoint.s..."  redis     running   6379/tcp

De plus, vérifiez les journaux pour les erreurs :

docker compose logs --tail=50 web

Pour les connexions à la base de données, vous pouvez exécuter une requête rapide depuis le réseau :

docker exec -it <container-name> psql -U postgres -c "SELECT 1;"
#  ?column?
# ----------
#         1

Vous pouvez également exécuter un conteneur de test dédié qui exécute des tests d'intégration et sort avec un code. Par exemple :

docker compose run --rm web npm test
# > test
# > jest --passWithNoTests
# PASS

Utilisez le code de sortie pour faire échouer le pipeline si les tests ne passent pas. Dans votre script CI, enveloppez la commande de test avec une vérification :

if ! docker compose run --rm web npm test; then
  echo "Tests failed"
  exit 1
fi

Contrôles de santé intégrés

Ajoutez des contrôles de santé à vos services Compose pour rendre la vérification plus robuste. Pour le service web, utilisez un contrôle de santé qui frappe le point de terminaison /health :

services:
  web:
    image: myapp:${TAG}
    healthcheck:
      test: ["CMD", "curl", "-fsS", "http://localhost/health"]
      interval: 10s
      timeout: 5s
      retries: 3
      start_period: 30s

Ensuite, utilisez docker compose up -d --wait (disponible dans Compose v2.20+) pour bloquer jusqu'à ce que les services soient sains ou échouent :

docker compose up -d --wait
# Container myapp-web-1  Healthy
# Container myapp-db-1   Healthy
# Container myapp-redis-1 Healthy

Si un conteneur ne devient pas sain dans la fenêtre de tentatives, docker compose up --wait sort avec un code non nul.

Modes de défaillance et récupération

Même avec une planification minutieuse, des échecs surviennent. Les modes de défaillance courants incluent :

  • Échecs de construction d'image dus à des dépendances manquantes ou des problèmes réseau
  • Erreurs de syntaxe du fichier Compose
  • Échecs de démarrage de service (par exemple, conflits de port, variables d'environnement manquantes)
  • Échecs de contrôle de santé après le déploiement
  • Erreurs de migration de base de données

Concevez votre pipeline pour échouer rapidement et laisser une trace claire. Par exemple, si une construction échoue, capturez le journal de construction et joignez-le à l'exécution CI. Dans GitHub Actions, vous pouvez utiliser la condition if: failure() pour téléverser les journaux comme artefacts :

- name: Capture build logs on failure
  if: failure()
  run: |
    docker compose logs > compose-logs.txt
- name: Upload logs
  if: failure()
  uses: actions/upload-artifact@v3
  with:
    name: compose-logs
    path: compose-logs.txt

Le retour en arrière est essentiel. Parce que vous étiquetez les images avec des identifiants uniques, revenir en arrière est aussi simple que de redéployer l'étiquette précédente. Stockez la dernière étiquette valide connue dans un fichier ou une variable d'environnement. Par exemple, dans un script de déploiement :

# Déployer la nouvelle étiquette
TAG=$NEW_TAG docker compose up -d
# Attendre la santé
sleep 10
if ! curl -fsS http://localhost/health; then
  echo "Deployment failed, rolling back to $LAST_GOOD_TAG"
  TAG=$LAST_GOOD_TAG docker compose up -d
fi

Si la nouvelle version introduit une migration de base de données qui ne peut pas être annulée automatiquement, vous pouvez avoir besoin d'une migration de retour distincte ou d'une restauration à partir de la sauvegarde. Documentez ces procédures et testez-les périodiquement. Dans votre base de code, gardez les scripts de migration versionnés et réversibles lorsque c'est possible. Pour une base de données PostgreSQL utilisant un outil comme node-pg-migrate, une migration de retour serait un fichier séparé qui annule les changements.

Une autre approche de récupération consiste à garder le conteneur précédent en cours d'exécution et à basculer le trafic uniquement après la vérification de santé. Cela peut être fait avec un équilibreur de charge ou en utilisant la mise à jour roulante intégrée de Docker avec des contrôles de santé. Pour des configurations Compose simples sur un seul hôte, vous pouvez utiliser la commande docker compose up -d --no-deps web pour recréer uniquement le conteneur web, en laissant les autres en cours d'exécution. Cependant, avec une étiquette unique, une nouvelle version échouée peut être annulée en exécutant TAG=$LAST_GOOD_TAG docker compose up -d.

Gestion des conflits de port

Les conflits de port se produisent lorsqu'un nouveau conteneur tente de se lier à un port déjà utilisé. Par exemple, si un ancien conteneur tourne toujours sur le port 80, le nouveau échoue :

Error response from daemon: driver failed programming external connectivity on endpoint myapp-web-1: Bind for 0.0.0.0:80 failed: port is already allocated

Évitez cela en utilisant un port hôte différent pour la nouvelle version, ou en arrêtant d'abord les anciens conteneurs. Dans une configuration Compose, vous pouvez déployer une nouvelle version à côté de l'ancienne (bleu-vert) en utilisant un nom de projet différent :

docker compose -p myapp-blue up -d
# Tester le bleu
curl -fsS http://localhost:8080/health  # si le bleu est mappé sur 8080
# Basculer le trafic
# Arrêter le vert
TAG=$LAST_GOOD_TAG docker compose -p myapp-green down

Cela nécessite un équilibreur de charge ou un proxy inverse pour basculer le trafic, mais cela peut réduire les temps d'arrêt.

Question rapide 2 sur 2

Dans le passage concernant la modification d'un fichier Compose pour la production, quelle option est citée comme raison de créer un fichier Compose spécifique à la production ?

Le passage mentionne la suppression des montages de volumes pour le code de l'application afin que le code reste dans le conteneur et ne puisse pas être modifié de l'extérieur comme un changement de production possible.

Pièges courants et comment les éviter

Lors de l'automatisation de Docker Compose dans le CI/CD, les équipes rencontrent souvent ces pièges. Les comprendre vous aide à concevoir un pipeline plus robuste.

1. Utiliser des étiquettes « latest » en production

Pourquoi cela arrive : Il est pratique d'utiliser latest et d'éviter de gérer les étiquettes.

Pourquoi c'est un problème : Vous ne pouvez pas revenir en arrière de manière fiable vers une version spécifique, et vous pourriez accidentellement déployer une construction non testée.

Comment l'éviter : Utilisez toujours des étiquettes uniques dérivées du SHA du commit ou du numéro de construction. Imposez cela en définissant TAG dans votre environnement CI et en l'utilisant dans votre fichier Compose via ${TAG}.

2. Surcharger incorrectement les fichiers Compose

Pourquoi cela arrive : Les équipes modifient le docker-compose.yml de base pour chaque environnement, conduisant à des divergences et des conflits de fusion.

Comment l'éviter : Utilisez des fichiers de surcharge spécifiques à l'environnement (docker-compose.prod.yml) et combinez-les avec les drapeaux -f. Ne modifiez jamais le fichier de base pour des paramètres spécifiques à l'environnement.

3. Ignorer les contrôles de santé dans le pipeline

Pourquoi cela arrive : Pour gagner du temps ou parce que le test de fumée est considéré comme suffisant.

Comment l'éviter : Définissez des contrôles de santé Docker pour chaque service et utilisez docker compose up -d --wait pour que le pipeline bloque jusqu'à ce que les services soient sains. Cela attrape les échecs de démarrage tôt.

4. Pas de retour en arrière automatisé

Pourquoi cela arrive : Le retour en arrière est considéré comme une opération manuelle, ou l'équipe suppose que les déploiements échouent rarement.

Comment l'éviter : Scénarisez le retour en arrière en utilisant la dernière étiquette valide connue. Stockez l'étiquette dans un fichier ou une variable d'environnement sur l'hôte cible, et assurez-vous que votre pipeline peut la redéployer automatiquement lorsque les contrôles de santé échouent.

5. Ignorer les migrations de base de données

Pourquoi cela arrive : Les équipes supposent que les changements d'application ne nécessitent pas de changements de schéma, ou elles exécutent les migrations manuellement.

Comment l'éviter : Incluez des étapes de migration dans votre pipeline, exécutez les migrations à l'intérieur d'un conteneur et versionnez vos scripts de migration. Pour Postgres, vous pourriez utiliser docker compose run --rm web npm run migrate. Gardez les procédures de sauvegarde et de retour en arrière documentées et testées.

Checklist opérationnelle

Utilisez cette checklist pour chaque déploiement. Chaque étape a un seul responsable (généralement l'ingénieur de release ou le développeur principal) et est revisitée à chaque déploiement, avec un audit mensuel pour assurer la conformité.

ÉtapeCommande ou actionRésultat attenduResponsable
Valider le fichier Composedocker compose config --quietAucune erreurIngénieur de release : Priya Shah
Construire l'imagedocker compose buildImage construite, étiquetéeIngénieur de release : Priya Shah
Exécuter les testsdocker compose run --rm web npm testCode de sortie 0Responsable QA : Marcus Chen
Déployer vers la préproductionTAG=staging docker compose up -dServices en cours d'exécutionIngénieur de release : Priya Shah
Vérifier la préproductioncurl -fsS http://staging/healthRenvoie 200Responsable QA : Marcus Chen
Déployer vers la productionTAG=$(git rev-parse HEAD) docker compose up -dServices en cours d'exécutionIngénieur de release : Priya Shah
Vérifier la productioncurl -fsS http://prod/healthRenvoie 200Responsable des opérations : Sofia Alvarez
Surveiller les journauxdocker compose logs -f --tail=100Aucune erreur critiqueResponsable des opérations : Sofia Alvarez

Après le déploiement, gardez un enregistrement de l'étiquette de l'image et du SHA du commit. Cela facilite le retour en arrière rapide et l'audit. Révisez cette checklist mensuellement lors d'une réunion post-déploiement avec l'équipe d'ingénierie, et ajustez les étapes à mesure que le pipeline évolue.

Conclusion

Automatiser Docker Compose avec des pipelines CI/CD est réalisable avec une planification minutieuse et une adoption incrémentale. Commencez par inventorier votre environnement et documenter les versions. Ensuite, implémentez des pratiques de configuration sécurisées telles que l'utilisation de fichiers de surcharge et d'étiquettes d'image uniques. Intégrez des étapes de vérification dans votre pipeline et préparez-vous aux échecs avec des procédures de retour en arrière et des contrôles de santé. Utilisez la checklist opérationnelle pour assurer la cohérence et attribuer des responsabilités claires. En suivant ces pratiques, vous pouvez obtenir des déploiements fiables, reproductibles et auditables. Commencez par un petit pilote, mesurez le succès et étendez progressivement.

Recherches connexes

Score de qualité de l’article

Utilité pour le lecteur 100%
  • check_circle Guide prêt à lire
  • check_circle Exemples pratiques inclus
  • check_circle URL d’article optimisée pour le SEO