DockerDevOpsDev

Docker Compose : du développement à la production

20 août 2026 · Sphinx-Digital

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é.