Docker Compose est souvent perçu comme un outil de développement. En réalité, bien structuré, il peut gérer des environnements de production sur des serveurs uniques ou des stacks de taille modérée — sans la complexité de Kubernetes.
Structure avec fichiers multiples
La clé d’un setup propre : un fichier de base commun, et des surcharges par environnement.
# docker-compose.yml — base commune à tous les environnements
services:
api:
image: registry.example.com/myapp:${IMAGE_TAG:-latest}
environment:
- DATABASE_URL=${DATABASE_URL}
- REDIS_URL=redis://redis:6379
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
networks:
- backend
db:
image: postgres:16-alpine
volumes:
- db_data:/var/lib/postgresql/data
environment:
POSTGRES_DB: myapp
POSTGRES_USER: myapp
POSTGRES_PASSWORD: ${DB_PASSWORD}
healthcheck:
test: ["CMD-SHELL", "pg_isready -U myapp"]
interval: 10s
timeout: 5s
retries: 5
networks:
- backend
redis:
image: redis:7-alpine
command: redis-server --appendonly yes
volumes:
- redis_data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
retries: 3
networks:
- backend
volumes:
db_data:
redis_data:
networks:
backend:
driver: bridge
# docker-compose.dev.yml — surcharges développement
services:
api:
build:
context: .
dockerfile: Dockerfile.dev
volumes:
- .:/app # hot reload du code source
- /app/node_modules
environment:
- DEBUG=true
- LOG_LEVEL=debug
ports:
- "8080:8080"
- "9229:9229" # port debugger Node.js
db:
ports:
- "5432:5432" # accès direct depuis l'IDE en dev
mailhog: # service uniquement en dev pour capturer les emails
image: mailhog/mailhog
ports:
- "1025:1025"
- "8025:8025"
networks:
- backend
# docker-compose.prod.yml — surcharges production
services:
api:
restart: unless-stopped
environment:
- DEBUG=false
- LOG_LEVEL=warning
deploy:
resources:
limits:
cpus: '1'
memory: 512M
reservations:
cpus: '0.25'
memory: 256M
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
nginx:
image: nginx:1.27-alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- ./nginx/certs:/etc/nginx/certs:ro
- ./nginx/logs:/var/log/nginx
depends_on:
- api
restart: unless-stopped
networks:
- backend
# Lancer en développement
docker compose -f docker-compose.yml -f docker-compose.dev.yml up
# Lancer en production
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
# Alias pratique dans .bashrc
alias dc-dev='docker compose -f docker-compose.yml -f docker-compose.dev.yml'
alias dc-prod='docker compose -f docker-compose.yml -f docker-compose.prod.yml'
Gestion des variables d’environnement
# .env.dev (jamais commité, listé dans .gitignore)
DATABASE_URL=postgresql://myapp:devpassword@db:5432/myapp
DB_PASSWORD=devpassword
IMAGE_TAG=latest
DEBUG=true
# .env.prod (géré via secrets manager ou variable CI/CD)
DATABASE_URL=postgresql://myapp:${PROD_DB_PASS}@db:5432/myapp
DB_PASSWORD=${PROD_DB_PASS}
IMAGE_TAG=1.2.3
DEBUG=false
# Utiliser un fichier .env spécifique
docker compose --env-file .env.prod -f docker-compose.yml -f docker-compose.prod.yml up -d
Healthchecks et dépendances
Sans healthcheck, depends_on attend seulement que le conteneur démarre — pas qu’il soit prêt. C’est source de race conditions classiques au démarrage.
services:
api:
depends_on:
db:
condition: service_healthy # attend que db soit healthy
redis:
condition: service_healthy
healthcheck:
test: ["CMD-SHELL", "curl -sf http://localhost:8080/healthz || exit 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s # grace period au démarrage
Mises à jour zero-downtime
# Mettre à jour un service sans couper les autres
IMAGE_TAG=1.2.4 docker compose -f docker-compose.yml -f docker-compose.prod.yml \
up -d --no-deps --build api
# Voir les logs pendant le redémarrage
docker compose logs -f api
# Script de déploiement complet
#!/usr/bin/env bash
set -euo pipefail
export IMAGE_TAG="${1:-latest}"
echo "Déploiement de la version $IMAGE_TAG"
# Pull de la nouvelle image
docker compose -f docker-compose.yml -f docker-compose.prod.yml pull api
# Redémarrage sans downtime
docker compose -f docker-compose.yml -f docker-compose.prod.yml \
up -d --no-deps api
# Vérification que l'API répond
sleep 10
curl -sf http://localhost:8080/healthz && echo "✅ Déploiement OK" || echo "❌ Vérifier les logs"
Notre formation Docker couvre Docker Compose et les stratégies de déploiement conteneurisé.