Aller au contenu principal
DockerConteneursFormation

Compose avancé : volumes, réseaux et scaling

30 min de lecture Apprendre Docker — Chapitre 6

Approfondis Compose avec les variables d'environnement, les profiles, les healthchecks et les bonnes pratiques.

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 .env externalise 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 :

  1. Crée un .env avec les credentials PostgreSQL et un port API configurable
  2. Écris un docker-compose.yml avec : une API (image nginx:alpine pour simplifier), une base PostgreSQL avec healthcheck, et un service Adminer avec le profile debug
  3. Lance la stack avec docker compose up -d et vérifie que tous les services sont healthy avec docker compose ps
  4. Active le profil debug : docker compose --profile debug up -d — Adminer doit être accessible sur le port 8080
  5. Vérifie la config résolue : docker compose config — les variables doivent être interpolées correctement
  6. Simule une panne : arrête PostgreSQL avec docker compose stop db, observe l’état des healthchecks, puis relance avec docker compose start db

🧠 À retenir :

  • Le fichier .env externalise 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 config est 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.

Obtenir 200$

Articles liés