Aller au contenu
Conteneurs & Orchestration high

Docker Compose : orchestrer vos conteneurs multi-services

28 min de lecture

Docker Compose déploie une application multi-conteneurs en une seule commande, à partir d'un fichier compose.yaml qui décrit toute votre architecture. Au terme de ce guide, vous saurez écrire ce fichier, faire communiquer vos services (application web + base de données), persister vos données avec des volumes, gérer vos secrets, itérer en direct avec watch, et épingler puis scanner vos images.

Le guide s'adresse aux débutants comme aux développeurs ayant déjà manipulé Docker. Prérequis : Docker installé. Résultat concret : une stack WordPress + MySQL fonctionnelle en 15 minutes, que vous pourrez adapter à vos propres projets. Toutes les commandes sont testées sur Docker Compose v5.

  • Architecture services/réseaux/volumes : comprendre les 3 concepts fondamentaux de Docker Compose et comment ils interagissent.
  • Écrire un compose.yaml multi-services : créer une stack WordPress + MySQL avec dépendances, volumes et variables.
  • Orchestrer en CLI : maîtriser up, down, logs, exec, config, watch et scale.
  • Fiabiliser le démarrage : healthchecks, depends_on, init containers pre_start.
  • Épingler et scanner : figer chaque image par digest et la passer à Trivy et Grype.
  • Connaître les limites : identifier quand migrer vers Docker Swarm ou Kubernetes.

Docker Compose est un outil qui permet de définir et lancer plusieurs conteneurs Docker en une seule commande. Au lieu d'exécuter plusieurs docker run avec des options complexes, vous décrivez votre architecture dans un fichier YAML et lancez tout avec docker compose up.

Analogie : imaginez un chef d'orchestre. Chaque musicien (conteneur) joue sa partition, mais c'est le chef (Compose) qui coordonne l'ensemble : qui démarre quand, qui communique avec qui, où sont stockées les partitions (données).

Pour mieux comprendre l'intérêt de Docker Compose, comparons deux approches pour déployer la même application (WordPress + MySQL).

Sans Docker Compose, vous exécutez manuellement chaque commande, dans le bon ordre, en vous souvenant de toutes les options. Si vous faites une erreur, vous recommencez. Et si un collègue veut reproduire votre environnement, vous devez lui transmettre toutes ces commandes.

Avec Docker Compose, tout est décrit dans un fichier versionnable. N'importe qui peut cloner votre repo et lancer docker compose up pour obtenir exactement le même environnement.

Sans ComposeAvec Compose
docker network create mynetUn seul fichier compose.yaml
docker run -d --name db --network mynet -e MYSQL_ROOT_PASSWORD=secret mysqlUne seule commande docker compose up
docker run -d --name wp --network mynet -e WORDPRESS_DB_HOST=db -p 8080:80 wordpressTout est versionné et reproductible
3 commandes à retenir et exécuter dans l'ordreArchitecture documentée dans le code

Docker Compose excelle quand vous contrôlez une seule machine et que la haute disponibilité n'est pas critique. C'est l'outil idéal pour reproduire un environnement de production localement, ou pour des environnements de test isolés.

En revanche, dès que vous devez répartir la charge sur plusieurs serveurs, gérer des pannes automatiquement, ou déployer avec zéro downtime, Compose montre ses limites. Dans ces cas, tournez-vous vers Kubernetes ou Docker Swarm.

✅ Utilisez Compose pour❌ N'utilisez pas Compose pour
Développement local multi-servicesProduction haute disponibilité
Tests d'intégrationDéploiement sur plusieurs serveurs
Démos et POCScaling automatique
CI/CD (environnements de test)Orchestration complexe (Kubernetes)

Vérifiez que Docker est installé et que Compose est disponible :

Fenêtre de terminal
docker --version
docker compose version

Résultat attendu : deux numéros de version s'affichent. La commande docker compose version doit afficher Docker Compose version v5.x.x ou plus récent.

Si docker compose version échoue, installez le plugin :

Fenêtre de terminal
# Ubuntu/Debian
sudo apt update
sudo apt install docker-compose-plugin
# Vérification
docker compose version

Avant d'écrire votre premier fichier, comprenez ces trois concepts fondamentaux.

Un service représente un conteneur avec toute sa configuration. C'est l'unité de base dans Docker Compose. Dans notre exemple, nous aurons deux services : wordpress (l'application web) et mysql (la base de données).

Pensez à un service comme une recette pour créer un conteneur. Cette recette spécifie quelle image utiliser, quelles variables d'environnement injecter, quels ports ouvrir. Quand vous lancez docker compose up, Compose lit ces recettes et crée les conteneurs correspondants.

Chaque service peut définir :

  • L'image Docker à utiliser (depuis Docker Hub ou un registre privé)
  • Les ports à exposer vers l'extérieur ou entre services
  • Les variables d'environnement pour configurer l'application
  • Les volumes à monter pour persister ou partager des données
  • Les dépendances vers d'autres services (qui doit démarrer en premier)
  • Les ressources (limites CPU, mémoire) et les politiques de redémarrage

Un réseau Docker est un espace de communication isolé où les conteneurs échangent des données. C'est comme un réseau local virtuel : les conteneurs connectés au même réseau peuvent se voir, ceux sur des réseaux différents sont isolés.

La force de Docker Compose, c'est la résolution DNS automatique. Dans un réseau Compose, chaque service est accessible par son nom. Le service wordpress contacte la base de données en utilisant mysql comme nom d'hôte, sans connaître son adresse IP.

Docker Compose crée automatiquement un réseau par défaut nommé <dossier>_default. Tous les services y sont connectés et communiquent sans configuration supplémentaire. Vous pouvez aussi créer des réseaux personnalisés pour isoler certains services (séparer le frontend du backend).

Les conteneurs sont éphémères par nature : quand vous supprimez un conteneur, tout ce qu'il contenait disparaît. C'est problématique pour une base de données, vous ne voulez pas perdre vos données à chaque redémarrage.

Un volume résout ce problème en stockant les données en dehors du conteneur, sur le système de fichiers de l'hôte. Même si le conteneur est supprimé et recréé, les données du volume sont préservées.

Docker propose trois types de stockage, chacun adapté à un usage :

TypeUsageExemple
Volume nomméDonnées persistantes (BDD, fichiers)db_data:/var/lib/mysql
Bind mountCode source en développement./src:/app
tmpfsDonnées temporaires en RAMtmpfs:/tmp

Pour illustrer ces concepts, nous allons déployer une stack simple : WordPress + MySQL. Le nom de fichier moderne est compose.yaml ; docker-compose.yml reste reconnu.

Architecture Docker Compose : WordPress et MySQL connectés via un réseau interne, avec un volume pour la persistance des données

  1. Créez un dossier pour votre projet

    Fenêtre de terminal
    mkdir ~/mon-wordpress && cd ~/mon-wordpress
  2. Créez le fichier compose.yaml

    Fenêtre de terminal
    touch compose.yaml
  3. Ajoutez la configuration suivante

    services:
    wordpress:
    image: wordpress@sha256:b2ceeaabb8fa90e12f32fdf5c2479f4cef4508255fb406bd19aa23b1ce59bc46 # WordPress 7.0
    ports:
    - "8080:80"
    environment:
    WORDPRESS_DB_HOST: mysql
    WORDPRESS_DB_USER: wordpress
    WORDPRESS_DB_PASSWORD: wordpress_password
    WORDPRESS_DB_NAME: wordpress
    depends_on:
    - mysql
    restart: unless-stopped
    mysql:
    image: mysql:8.0@sha256:7dcddc01f13bab2f15cde676d44d01f61fc9f99fe7785e86196dfc07d358ae2b # MySQL 8.0.46
    environment:
    MYSQL_DATABASE: wordpress
    MYSQL_USER: wordpress
    MYSQL_PASSWORD: wordpress_password
    MYSQL_ROOT_PASSWORD: root_secret_password
    volumes:
    - db_data:/var/lib/mysql
    restart: unless-stopped
    volumes:
    db_data:

    Explications :

    • services:, définit les conteneurs à créer.
    • image: ...@sha256:..., l'image officielle épinglée par digest.
    • ports: "8080:80", expose le port 80 du conteneur sur le port 8080 de la machine.
    • WORDPRESS_DB_HOST: mysql, WordPress contacte MySQL via son nom de service.
    • depends_on:, WordPress attend que MySQL démarre (mais pas qu'il soit prêt).
    • volumes: db_data:/var/lib/mysql, les données MySQL sont persistées.
    • restart: unless-stopped, redémarre automatiquement sauf arrêt manuel.

Quand vous exécutez docker compose up, Compose orchestre la création de l'infrastructure. Voici ce qui se passe en coulisses.

Workflow Docker Compose : étapes d'exécution de docker compose up

  1. Lancez la stack

    Fenêtre de terminal
    docker compose up -d

    L'option -d (detached) lance les conteneurs en arrière-plan.

    Résultat attendu :

    [+] Running 3/3
    ✔ Network mon-wordpress_default Created
    ✔ Container mon-wordpress-mysql-1 Started
    ✔ Container mon-wordpress-wordpress-1 Started
  2. Vérifiez que les conteneurs tournent

    Fenêtre de terminal
    docker compose ps

    Résultat attendu (le format par défaut en v5 est large) :

    NAME IMAGE SERVICE STATUS PORTS
    mon-wordpress-mysql-1 mysql:8.0 mysql Up 8 seconds 3306/tcp, 33060/tcp
    mon-wordpress-wordpress-1 wordpress wordpress Up 8 seconds 0.0.0.0:8080->80/tcp, [::]:8080->80/tcp

    Le mapping de port apparaît maintenant en IPv4 et IPv6. Pour un affichage compact, utilisez docker compose ps --format "table {{.Name}}\t{{.Status}}\t{{.Ports}}".

  3. Testez l'application

    Ouvrez votre navigateur à l'adresse http://localhost:8080. Vous devriez voir l'écran d'installation de WordPress.

  4. Consultez les logs si besoin

    Fenêtre de terminal
    docker compose logs
    # Ou pour un service précis :
    docker compose logs mysql

Mettre des mots de passe en clair dans compose.yaml pose deux problèmes : c'est un risque de sécurité si vous versionnez le fichier (les secrets se retrouvent dans l'historique Git), et c'est peu pratique quand vous avez des environnements différents (dev, staging, prod).

La solution : externaliser vos variables dans un fichier .env. Docker Compose lit automatiquement ce fichier s'il existe dans le même dossier, et remplace les variables ${...} par leurs valeurs.

Fenêtre de terminal
# Fichier .env (même dossier que compose.yaml)
MYSQL_ROOT_PASSWORD=super_secret_root
MYSQL_PASSWORD=wordpress_password
WORDPRESS_DB_PASSWORD=wordpress_password

Puis référencez-les dans votre Compose :

services:
mysql:
image: mysql:8.0@sha256:7dcddc01f13bab2f15cde676d44d01f61fc9f99fe7785e86196dfc07d358ae2b # MySQL 8.0.46
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_PASSWORD: ${MYSQL_PASSWORD}

Vérifiez la substitution avant de démarrer avec docker compose config, qui affiche la configuration finale résolue.

Les fichiers .env sont pratiques, mais les variables d'environnement sont visibles dans les logs, les processus et via docker inspect. Pour des secrets vraiment sensibles, Docker propose un mécanisme plus sûr : les secrets.

Le contenu sensible est stocké dans un fichier séparé et monté en lecture seule dans le conteneur, à l'emplacement /run/secrets/<nom>. L'application lit le fichier au lieu d'une variable d'environnement. Le secret n'apparaît jamais dans l'environnement ni dans les logs.

services:
mysql:
image: mysql:8.0@sha256:7dcddc01f13bab2f15cde676d44d01f61fc9f99fe7785e86196dfc07d358ae2b # MySQL 8.0.46
environment:
MYSQL_ROOT_PASSWORD_FILE: /run/secrets/mysql_root_password
secrets:
- mysql_root_password
secrets:
mysql_root_password:
file: ./secrets/mysql_root_password.txt

Le mot de passe est lu depuis le fichier monté, jamais exposé dans l'environnement.

Vous avez remarqué le depends_on dans notre configuration WordPress. Cette directive garantit que MySQL démarre avant WordPress. Mais attention : démarré ne signifie pas prêt.

Docker considère MySQL comme démarré dès que le processus est lancé. Or MySQL a besoin de quelques secondes pour initialiser ses bases et ouvrir son port. Si WordPress se connecte pendant cette initialisation, il échoue avec « Error establishing database connection ».

La solution : les healthchecks. Un healthcheck est une commande que Docker exécute régulièrement pour vérifier si le service est vraiment opérationnel. Avec condition: service_healthy, le service dépendant attend que le healthcheck soit positif.

services:
mysql:
image: mysql:8.0@sha256:7dcddc01f13bab2f15cde676d44d01f61fc9f99fe7785e86196dfc07d358ae2b # MySQL 8.0.46
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 5
wordpress:
image: wordpress@sha256:b2ceeaabb8fa90e12f32fdf5c2479f4cef4508255fb406bd19aa23b1ce59bc46 # WordPress 7.0
depends_on:
mysql:
condition: service_healthy

Au démarrage, la séquence observée est nette : mysql Started puis mysql Waiting puis mysql Healthy, et seulement ensuite wordpress Started. WordPress ne démarre qu'une fois MySQL réellement prêt.

Compose v5.3 a introduit les init containers natifs avec le champ pre_start : un conteneur éphémère qui s'exécute après la création du conteneur de service mais avant son démarrage. C'est l'endroit idéal pour une migration de base de données, préparer un volume ou fixer des permissions, sans polluer l'image applicative.

services:
web:
image: nginx:alpine@sha256:54f2a904c251d5a34adf545a72d32515a15e08418dae0266e23be2e18c66fefa # nginx 1.31.2
ports:
- "8080:80"
pre_start:
- command: sh -c "echo 'page initialisée par le pre_start' > /usr/share/nginx/html/index.html"
volumes:
- web_root:/usr/share/nginx/html
volumes:
web_root:

L'init container partage les volumes du service : ici il écrit dans web_root, et nginx sert ensuite cette page. Vous pouvez aussi lui donner sa propre image: (par exemple image: busybox), à condition qu'elle soit disponible localement, sinon le démarrage échoue avec No such image.

Deux hooks complètent le cycle de vie : post_start (après le démarrage du conteneur) et pre_stop (avant son arrêt, ignoré si le conteneur s'arrête de lui-même).

services:
app:
image: nginx:alpine@sha256:54f2a904c251d5a34adf545a72d32515a15e08418dae0266e23be2e18c66fefa # nginx 1.31.2
post_start:
- command: sh -c "echo prêt > /tmp/ready"
pre_stop:
- command: ./drain.sh

Jusqu'ici nous avons utilisé des images publiques. Dans un projet réel, vous aurez souvent votre propre code à conteneuriser. Plutôt que de builder manuellement avec docker build, demandez à Compose de le faire.

La directive build remplace image et indique où trouver le Dockerfile :

services:
api:
build:
context: ./backend # Dossier contenant le code et le Dockerfile
dockerfile: Dockerfile # Optionnel si nom par défaut
ports:
- "3000:3000"

Avec docker compose up --build, Compose construit l'image puis lance le conteneur. En v5, cette construction est déléguée à Docker Bake : la sortie mentionne load local bake definitions. Le comportement reste identique à docker build, avec le cache et les fonctionnalités de BuildKit.

Recompiler à la main à chaque changement de code casse le rythme. docker compose watch surveille vos fichiers et synchronise ou reconstruit automatiquement le conteneur. C'est le remplaçant moderne du cycle « modifier, --build, relancer ».

services:
web:
image: nginx:alpine@sha256:54f2a904c251d5a34adf545a72d32515a15e08418dae0266e23be2e18c66fefa # nginx 1.31.2
ports:
- "8080:80"
develop:
watch:
- action: sync
path: ./app
target: /usr/share/nginx/html

Lancez la stack puis la surveillance :

Fenêtre de terminal
docker compose up -d
docker compose watch

Modifiez un fichier de ./app : il est synchronisé en direct dans le conteneur, sans rebuild. Trois actions existent : sync (copie le fichier), rebuild (reconstruit l'image, pour un changement de dépendances) et sync+restart (synchronise puis redémarre le service, pour un fichier de configuration).

Docker Compose peut scaler horizontalement un service en créant plusieurs réplicas identiques. C'est utile pour répartir la charge ou simuler un environnement distribué.

Fenêtre de terminal
# Lancer 3 instances du service web
docker compose up -d --scale web=3
docker compose ps

Avec un port fixe, cette commande échoue : Docker ne peut pas mapper plusieurs conteneurs sur le même port hôte.

Error response from daemon: ... Bind for 0.0.0.0:8080 failed: port is already allocated

La solution est une plage de ports, qui attribue un port distinct à chaque réplica :

services:
web:
image: nginx:alpine@sha256:54f2a904c251d5a34adf545a72d32515a15e08418dae0266e23be2e18c66fefa # nginx 1.31.2
ports:
- "8080-8082:80"
NAME PORTS
projet-web-1 0.0.0.0:8080->80/tcp, [::]:8080->80/tcp
projet-web-2 0.0.0.0:8081->80/tcp, [::]:8081->80/tcp
projet-web-3 0.0.0.0:8082->80/tcp, [::]:8082->80/tcp

Vous pouvez aussi fixer le nombre de réplicas dans le fichier avec deploy.replicas. Contrairement à ce qu'on lit parfois, ce champ n'est plus réservé à Swarm : docker compose up l'honore et crée bien le nombre demandé de conteneurs.

services:
web:
image: nginx:alpine@sha256:54f2a904c251d5a34adf545a72d32515a15e08418dae0266e23be2e18c66fefa # nginx 1.31.2
deploy:
replicas: 3

Limites du scaling avec Compose : pas de load balancer intégré (il faut un reverse proxy), pas de répartition intelligente, pas de scaling selon la charge. Pour ces besoins, passez à Docker Swarm ou Kubernetes.

Les restart policies définissent le comportement d'un conteneur en cas d'arrêt (crash, arrêt manuel, reboot serveur). C'est crucial pour la résilience.

PolitiqueComportementUsage recommandé
noNe jamais redémarrer (par défaut)Jobs batch, tâches ponctuelles
alwaysRedémarre toujours, même après arrêt manuel ou rebootServices critiques (BDD, API)
unless-stoppedRedémarre sauf si arrêté manuellementServices persistants en production
on-failureRedémarre uniquement en cas de crash (exit code ≠ 0)Services instables, diagnostics
services:
db:
image: postgres:16-alpine@sha256:23e88eb049fd5d54894d70100df61d38a49ed97909263f79d4ff4c30a5d5fca2 # PostgreSQL 16.11
restart: always # BDD toujours disponible
worker:
image: mon-worker:1.4.0 # votre image, épinglée par tag ou digest
restart: on-failure # redémarre uniquement en cas de crash

Vérifiez le compteur de redémarrages avec docker inspect <conteneur> | grep -A 5 RestartCount.

Les profils définissent des services optionnels qui ne démarrent que si explicitement demandés. Parfait pour les outils de debug (pgadmin, adminer), les services de développement, ou les mocks de test.

services:
db:
image: postgres:16-alpine@sha256:23e88eb049fd5d54894d70100df61d38a49ed97909263f79d4ff4c30a5d5fca2 # PostgreSQL 16.11
# Toujours démarré (pas de profil)
pgadmin:
image: dpage/pgadmin4:9.7 # épinglez par digest en production
profiles: ["debug"] # démarré uniquement avec --profile debug
ports:
- "5050:80"
Fenêtre de terminal
# Démarrage normal : db uniquement
docker compose up -d
# Démarrage avec pgadmin pour debug
docker compose --profile debug up -d

Sans profil, seul db démarre ; avec --profile debug, db et pgadmin démarrent. On combine plusieurs profils en répétant l'option (--profile debug --profile monitoring).

Dans un projet réel, vous avez souvent des configurations différentes selon l'environnement. Docker Compose fusionne plusieurs fichiers YAML, plus maintenable que de tout dupliquer.

Fenêtre de terminal
# Développement : base + override (auto-chargé)
docker compose up -d
# Production : base + prod (ignore override)
docker compose -f compose.yaml -f compose.prod.yml up -d

Chaque fichier écrase les propriétés du précédent : l'ordre des -f est important, le fichier de base d'abord. Les scalaires (image, restart) sont écrasés, les listes (ports, volumes) fusionnées. Vérifiez le résultat final avec docker compose config.

Une image tirée par tag mouvant (:latest, :8) peut changer sous vos pieds : le même fichier Compose déploie une image différente d'un jour à l'autre. Pire, une image compromise ou vulnérable passe inaperçue. Deux réflexes règlent cela : épingler par digest et scanner.

Le digest (@sha256:...) identifie le contenu exact d'une image, de façon immuable. Récupérez-le après un docker pull :

Fenêtre de terminal
docker pull nginx:alpine
docker inspect --format '{{index .RepoDigests 0}}' nginx:alpine
# nginx@sha256:54f2a904c251d5a34adf545a72d32515a15e08418dae0266e23be2e18c66fefa

Reportez ce digest dans le fichier, en gardant le tag en commentaire pour la lisibilité :

services:
web:
image: nginx:alpine@sha256:54f2a904c251d5a34adf545a72d32515a15e08418dae0266e23be2e18c66fefa # nginx 1.31.2

Vous tirez désormais toujours la même image, quel que soit le déplacement du tag. Pour automatiser les mises à jour de ces digests, un outil comme Renovate ouvre des pull requests quand une nouvelle version paraît.

Épingler fige l'image, mais ne dit rien de ses vulnérabilités. Deux scanners de référence répondent à cette question. Trivy donne un résumé par sévérité :

Fenêtre de terminal
trivy image mysql:8.0
# mysql:8.0 (oracle 9.7)
# Total: 80 (UNKNOWN: 0, LOW: 2, MEDIUM: 32, HIGH: 46, CRITICAL: 0)

Le contraste avec une image minimale est frappant : la même commande sur nginx:alpine renvoie 0 vulnérabilité. La première leçon de sécurité tient là : une image slim (Alpine, distroless) réduit drastiquement la surface d'attaque.

Grype apporte un second regard, avec un score EPSS (probabilité d'exploitation) et un score de risque :

Fenêtre de terminal
grype nginx:alpine
# NAME INSTALLED FIXED IN TYPE VULNERABILITY SEVERITY EPSS RISK
# tiff 4.7.1-r0 apk CVE-2023-52356 High 2.2% (80th) 1.6
# curl 8.19.0-r0 apk CVE-2026-5773 High 0.5% (41st) 0.4

Détail instructif : sur nginx:alpine, Grype signale des CVE (tiff, curl) que Trivy compte à zéro. Ce n'est pas un bug, c'est la réalité de deux bases de vulnérabilités et de deux logiques de correspondance différentes. La conclusion pratique : ne dépendez pas d'un seul scanner, croisez-les, et intéressez-vous aux failles corrigées (FIXED IN renseigné) que vous pouvez éliminer par une mise à jour.

Les deux outils scannent aussi par digest, exactement ce que vous avez épinglé :

Fenêtre de terminal
trivy image nginx@sha256:54f2a904c251d5a34adf545a72d32515a15e08418dae0266e23be2e18c66fefa
grype nginx@sha256:54f2a904c251d5a34adf545a72d32515a15e08418dae0266e23be2e18c66fefa

En CI, faites échouer le pipeline sur les vulnérabilités critiques (trivy image --exit-code 1 --severity CRITICAL <image>) pour ne jamais déployer une image trouée.

Voici les commandes du quotidien. La plupart s'exécutent depuis le dossier contenant votre compose.yaml.

CommandeDescription
docker compose up -dDémarre tous les services en arrière-plan
docker compose downArrête et supprime conteneurs et réseaux
docker compose down -vIdem + supprime les volumes (⚠️ perte de données)
docker compose psListe les conteneurs du projet
docker compose ps --format jsonSortie JSON Lines (un objet par ligne), pour le scripting
docker compose logs -fAffiche les logs en temps réel
docker compose exec mysql bashOuvre un shell dans le conteneur MySQL
docker compose watchSynchronise le code en direct pendant le développement
docker compose restartRedémarre tous les services
docker compose pullMet à jour les images
docker compose configValide et affiche la configuration finale

Votre premier réflexe face à un problème : consulter les logs avec docker compose logs, ils contiennent souvent la réponse.

SymptômeCause probableSolution
port is already allocatedUn autre service utilise déjà le portChangez le port dans ports: ou arrêtez l'autre service
"Error establishing database connection"La BDD n'est pas encore prêteAjoutez un healthcheck + condition: service_healthy
Les données disparaissent après downVous avez utilisé down -v qui supprime les volumesUtilisez down sans -v
network not foundLe réseau a été supprimé manuellementRelancez docker compose up
Conteneur en restart loopL'application plante au démarrageConsultez docker compose logs <service>
pre_start ignoréCompose antérieur à v5.3Mettez à jour Compose (docker compose version)
Init container No such imageL'image du pre_start n'est pas disponibleTirez-la (docker pull) ou réutilisez l'image du service
Changements non appliquésCompose utilise l'ancienne image/configdocker compose up -d --build --force-recreate

Docker Compose est parfait pour le développement local, mais ce n'est pas un orchestrateur de production : il ne gère qu'une seule machine.

Si votre serveur tombe, vos conteneurs s'arrêtent sans serveur de secours. Si votre application a besoin de plus de ressources, vous ne pouvez pas répartir la charge sur plusieurs serveurs. Pour ces besoins, il faut un véritable orchestrateur.

FonctionnalitéDocker ComposeDocker SwarmKubernetes
Orchestration multi-serveurs
Load balancing automatique
Redémarrage sur panne de serveur
Scaling automatique (HPA)
Rolling updates
RBAC et sécurité avancéeBasique
ComplexitéFaibleMoyenneÉlevée
Cas d'usageDev/test/CIPetit clusterProduction

Règle simple : Compose en développement ; pour la production, Kubernetes (ou au minimum Docker Swarm).

  1. Docker Compose orchestre plusieurs conteneurs avec un seul fichier YAML et une seule commande.
  2. Trois concepts : les services (conteneurs), les réseaux (communication) et les volumes (persistance).
  3. docker compose up -d démarre tout, docker compose down arrête tout, watch synchronise le code en direct.
  4. Fiabilisez le démarrage avec les healthchecks (condition: service_healthy) et les init containers (pre_start, Compose v5.3+).
  5. Externalisez vos secrets (.env ou secrets Docker), jamais en clair dans le YAML versionné.
  6. Épinglez chaque image par digest (@sha256) et scannez-la avec Trivy et Grype.
  7. Compose n'est pas pour la production : pas de haute disponibilité, pas de scaling multi-serveurs.
  • Docker Compose v5 installé (docker compose version)
  • Fichier compose.yaml créé et validé (docker compose config)
  • Images épinglées par digest et scannées (Trivy / Grype)
  • Services démarrés (docker compose up -d)
  • Communication inter-services fonctionnelle (WordPress accède à MySQL)
  • Données persistées (volume db_data)
  • Secrets externalisés (.env ou secrets Docker), .env dans .gitignore

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracking. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn