Tu sais lancer une stack Compose avec docker compose up. Mais en entreprise, une stack qui tourne ne suffit pas — il faut qu’elle soit fiable, configurable et maintenable. Ce chapitre t’emmène au niveau supérieur : variables d’environnement externalisées, profiles pour activer des services à la demande, et healthchecks pour un démarrage sans crash. C’est la différence entre un side-project et une infra pro.
Pourquoi maîtriser Compose avancé
Quand tu déploies une stack en équipe, les problèmes arrivent vite. Les mots de passe finissent en dur dans le YAML, commitées sur Git. L’API crashe au démarrage parce que PostgreSQL n’est pas encore prêt. Les outils de debug tournent en production et bouffent des ressources pour rien.
Compose avancé résout ces trois problèmes avec trois mécanismes :
- Le fichier
.envexternalise les secrets et la configuration - Les profiles permettent d’activer des services uniquement quand tu en as besoin
- Les healthchecks garantissent que chaque service est réellement prêt avant que les dépendants démarrent
🔥 Cas réel : Une startup SaaS avait des crashs aléatoires au déploiement. Leur API démarrait avant PostgreSQL. Résultat : connection refused, restart en boucle, alertes PagerDuty à 3h du matin. Un healthcheck + depends_on: condition: service_healthy a réglé le problème en 5 lignes de YAML.
Comprendre les mécanismes avancés
Variables d’environnement et fichier .env
Compose charge automatiquement un fichier .env situé à la racine du projet. Tu y mets tes secrets et ta configuration, et tu références les variables dans ton docker-compose.yml avec la syntaxe ${VARIABLE}.
Voici un fichier .env typique et son utilisation dans Compose :
# .env — à ajouter dans .gitignore !
POSTGRES_USER=devops
POSTGRES_PASSWORD=S3cur3P@ss!
POSTGRES_DB=appdb
API_PORT=5000
# docker-compose.yml — utilisation des variables
services:
db:
image: postgres:16-alpine
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
api:
build: ./api
ports:
- "${API_PORT}:5000"
env_file:
- ./api/.env # Fichier .env spécifique au service
💡 Tip DevOps : Crée toujours un .env.example avec des valeurs fictives et commite-le. Tes collègues sauront quelles variables configurer sans voir tes vrais secrets. La syntaxe ${VARIABLE:-default} permet de définir une valeur de repli.
Profiles : services à la demande
Les profiles regroupent des services optionnels — typiquement les outils de debug ou d’administration — qui ne démarrent pas par défaut.
Un service sans profile démarre toujours. Un service avec profile ne démarre que si tu l’actives explicitement :
services:
api:
build: ./api # Pas de profile = toujours actif
db:
image: postgres:16-alpine # Toujours actif
adminer:
image: adminer:latest
ports:
- "8080:8080"
profiles: [debug] # Uniquement avec --profile debug
redis-commander:
image: rediscommander/redis-commander
ports:
- "8081:8081"
profiles: [debug] # Uniquement avec --profile debug
Healthchecks : démarrage fiable
C’est le mécanisme qui manque à 90% des stacks Compose débutantes. Sans healthcheck, depends_on garantit seulement que le conteneur est démarré — pas que le service à l’intérieur est prêt.
Ce healthcheck vérifie que PostgreSQL accepte réellement des connexions, et bloque le démarrage de l’API tant que la base n’est pas prête :
services:
db:
image: postgres:16-alpine
healthcheck:
test: ["CMD-SHELL", "pg_isready -U devops -d appdb"]
interval: 5s
timeout: 3s
retries: 5
start_period: 10s
api:
build: ./api
depends_on:
db:
condition: service_healthy # Attend que db soit healthy
⚠️ Attention : Sans condition: service_healthy, ton API va tenter de se connecter à PostgreSQL qui n’accepte pas encore de connexions. Résultat : crash, restart, et potentiellement une boucle infinie si ta restart policy est always.
Commandes essentielles
Voici les commandes que tu utiliseras au quotidien, regroupées par usage :
# Démarrer / Arrêter
docker compose up -d # Lancer en arrière-plan
docker compose up -d --build # Rebuild + lancer
docker compose --profile debug up -d # Activer un profil
docker compose down # Stopper (garde volumes)
docker compose down -v # Stopper + supprimer volumes
# Observer
docker compose ps # État des conteneurs + health
docker compose logs -f api # Logs en streaming
docker compose config # YAML résolu (debug variables)
# Intervenir
docker compose exec db psql -U devops -d appdb # Shell dans un conteneur
docker compose restart api # Redémarrer un service
docker compose up -d --scale api=3 # Scaler un service
docker compose build --no-cache api # Rebuild sans cache
💡 Tip DevOps : docker compose config est ton meilleur ami pour débugger les variables d’environnement. Il affiche le YAML final avec toutes les variables interpolées — tu vois immédiatement si une valeur est manquante ou mal remplacée.
Cas concret : stack e-commerce en entreprise
Imaginons que tu gères la stack d’une plateforme e-commerce. Tu as une API Node.js, une base PostgreSQL, un cache Redis, et tu veux pgAdmin uniquement en dev.
Voici comment structurer ça proprement avec les trois mécanismes qu’on vient de voir :
services:
api:
build: ./api
ports:
- "${API_PORT:-3000}:3000"
env_file: [./api/.env]
depends_on:
db: { condition: service_healthy }
redis: { condition: service_healthy }
restart: unless-stopped
deploy:
resources:
limits: { memory: 512M, cpus: "0.5" }
db:
image: postgres:16-alpine
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
interval: 5s
timeout: 3s
retries: 5
start_period: 10s
restart: unless-stopped
redis:
image: redis:7-alpine
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 3
restart: unless-stopped
pgadmin:
image: dpage/pgadmin4
ports: ["8080:80"]
environment:
PGADMIN_DEFAULT_EMAIL: ${PGADMIN_EMAIL:-admin@local.dev}
PGADMIN_DEFAULT_PASSWORD: ${PGADMIN_PASSWORD:-admin}
profiles: [debug]
volumes:
pgdata:
🧠 À retenir : Cette stack combine les trois piliers — .env pour la config, profiles pour pgAdmin en dev uniquement, healthchecks pour un démarrage fiable. C’est le pattern que tu retrouveras dans la majorité des projets professionnels.
Pièges fréquents
1. depends_on sans condition — Le piège classique. Sans condition: service_healthy, tes services démarrent dans l’ordre mais sans attendre que le service soit réellement prêt. Toujours utiliser la forme longue avec condition.
2. image: postgres:latest — Le tag latest change sans prévenir. Un mardi matin, ta stack casse parce que l’image a été mise à jour. Utilise toujours un tag explicite comme postgres:16-alpine.
3. docker compose down -v en prod — Le flag -v supprime les volumes nommés. Tes données PostgreSQL, Redis, tout disparaît. En production, utilise docker compose down sans -v, toujours.
4. Secrets dans le YAML — Si tes mots de passe sont dans docker-compose.yml, ils sont dans Git, donc visibles par toute l’équipe (et potentiellement sur GitHub public). Externalise dans .env et ajoute-le au .gitignore.
5. Oublier restart: unless-stopped — Sans restart policy, un conteneur qui crashe reste arrêté. En dev c’est acceptable, en staging/prod c’est un incident.
⚠️ Attention : docker compose down -v est irréversible. Il n’y a pas de confirmation, pas de corbeille. Si tu as besoin de repartir de zéro, fais un backup du volume avant : docker run --rm -v pgdata:/data -v $(pwd):/backup alpine tar czf /backup/pgdata.tar.gz /data.
Exercice pratique
Mets en place une stack complète en appliquant tout ce qu’on a vu :
- Crée un
.envavec les credentials PostgreSQL et un port API configurable - Écris un
docker-compose.ymlavec : une API (imagenginx:alpinepour simplifier), une base PostgreSQL avec healthcheck, et un service Adminer avec le profiledebug - Lance la stack avec
docker compose up -det vérifie que tous les services sonthealthyavecdocker compose ps - Active le profil debug :
docker compose --profile debug up -d— Adminer doit être accessible sur le port 8080 - Vérifie la config résolue :
docker compose config— les variables doivent être interpolées correctement - Simule une panne : arrête PostgreSQL avec
docker compose stop db, observe l’état des healthchecks, puis relance avecdocker compose start db
🧠 À retenir :
- Le fichier
.envexternalise la configuration — ne commite jamais de secrets - Les profiles séparent les outils de debug du runtime de production
- Les healthchecks +
depends_on: condition: service_healthy= démarrage fiable et prévisible - Toujours utiliser des tags d’image explicites, jamais
latest docker compose configest l’outil de debug n°1 pour les variables d’environnement
🧪 Lab pratique
Mets en pratique ce que tu viens d’apprendre dans un environnement interactif, directement dans ton navigateur. Pas besoin d’installer quoi que ce soit !
🚀 Lancer le lab sur Killercoda →
➡️ La suite
Dans le prochain chapitre, on parle Docker en production : sécurité rootless, limites de ressources, logging et tout ce qui sépare un setup de dev d’une infra solide.
🖥️ Pratique sur ton propre serveur
Pour suivre Apprendre Docker en conditions réelles, tu as besoin d'un VPS. DigitalOcean offre 200$ de crédit gratuit pour démarrer.
Contenu réservé aux abonnés
Ce chapitre fait partie de la formation complète. Abonne-toi pour débloquer tous les contenus.
Débloquer pour 29 CHF/moisLe chapitre 1 de chaque formation est gratuit.
Série pas encore débloquée
Termine la série prérequise d'abord pour accéder à ce contenu.
Aller à la série prérequiseSérie : Apprendre Docker
6 / 10- Pourquoi Docker ? Les conteneurs expliqués
- Tes premières commandes Docker
- Ton premier Dockerfile
- Dockerfile avancé : multi-stage et optimisation
- Docker Compose : orchestrer tes services
- 6 Compose avancé : volumes, réseaux et scaling
- 7 Docker en production : logs et healthchecks
- 8 Déploiement et CI/CD avec Docker
- 9 Sécurité Docker : rootless et isolation
- 10 Scanning et conformité Docker
Sur cette page
Articles liés
Pourquoi Docker ? Les conteneurs expliqués
Découvre ce que sont les conteneurs, comment ils se distinguent des machines virtuelles et comprends l'architecture Docker.
Tes premières commandes Docker
Prends en main Docker avec tes premières commandes : docker run, pull, ps, images, exec et le cycle de vie des conteneurs.
Ton premier Dockerfile
Apprends à écrire un Dockerfile avec les instructions essentielles : FROM, COPY, RUN, CMD et docker build.