09

Compose Avancé

Sécuriser les démarrages et l'environnement

Le lancement des conteneurs pose un problème fondamental : Un service démarré ne signifie pas qu'il est prêt à l'usage. Par exemple, au démarrage, PostgreSQL prend 5 à 10 secondes pour allouer sa RAM et monter ses fichiers. Si votre API tente de s'y connecter immédiatement (à la milliseconde 1), elle plantera violemment (`Connexion Refusée`).

Le Problème du "Depends_on" classique

API Node.js Tente de se connecter
"Tu es là ?" -> BOOM 💥
PostgreSQL S'initialise (Démarré mais pas prêt)

Historiquement on utilisait `depends_on: [db]`. Mais cela attend simplement que le processus Docker de la DB *démarre*. Pas qu'elle soit *Healthy* (qu'elle écoute vraiment les requêtes). La solution ultime est le Healthcheck.

docker-compose.yml (Bonne pratique)
services:
  api:
    image: mon-api
    depends_on:
      db:
        condition: service_healthy    # ⏳ L'API restera "Paused" tant que ce n'est pas Healthy

  db:
    image: postgres:15
    healthcheck:                      # 🩺 La sonde de Prod
      test: ["CMD-SHELL", "pg_isready -U superadmin"] # Ping interne natif PostgreSQL
      interval: 5s                    # Vérifie toutes les 5 secondes
      timeout: 3s                     # Si ça prend plus de 3s, c'est mort
      retries: 5                      # Au bout de 5 morts, le conteneur passe de "Starting" à "Unhealthy"

Désintégrer le .env (Variables d'Environnement)

Ne mettez JAMAIS de mots de passe ou clés d'API dans votre fichier docker-compose.yml. Si ce fichier finit sur GitHub (et il y finira, tôt ou tard !), toutes vos clés d'API et mots de passe seront exposés publiquement en clair. Utilisez l'injection par fichier env_file et le fichier .env, qui lui ne sera jamais commité.

Checklist : Sécuriser les secrets

Cochez chaque étape validée avant de pousser votre projet sur Git :

.env (Fichier à mettre ABSOLUMENT dans .gitignore)
DB_PASSWORD=SuperSecretPassWord123!
JWT_SECRET=x8Lkj29#
docker-compose.yml
services:
  db:
    image: postgres:15
    env_file:             # Docker injecte tout le fichier .env en un coup !
      - .env
      
  api:
    image: mon-api
    environment:
      - DATABASE_PASSWORD=${DB_PASSWORD}  # Injection sélective. La syntaxe ${VAR} appelle l'hôte !

Les Profils (Séparer le Dev de la Prod)

Vous souhaitez un conteneur d'administration visuelle (comme Adminer ou PgAdmin) pour vous aider en dev local. Mais si vous lancez en production, vous ne voulez surtout pas inclure ce service potentiellement vulnérable ! C'est le rôle des Profils.

docker-compose.yml
services:
  api:
    image: mon-api
    # (Démarre toujours par défaut)

  adminer:
    image: adminer
    profiles: 
      - debug    # 🛡️ Ne démarrera JAMAIS sauf ordre contraire !
    ports:
      - "8080:8080"
💡 Utilisation CLI En production : docker compose up -d (L'Adminer est ignoré).
En developpement : docker compose --profile debug up -d (L'API et l'Adminer démarrent).

Bonus : Composer plusieurs fichiers (Override)

Puisque Compose lit plusieurs fichiers dans l'ordre, une astuce Pro consiste à définir une configuration de base partagée (docker-compose.yml), et à la surcharger avec un second fichier spécifique à l'environnement. Pas de copier-coller, pas de risque d'oublier de synchroniser les deux !

docker-compose.yml (base commune)
services:
  api:
    build: .
    environment:
      - NODE_ENV=production
docker-compose.dev.yml (surcharge Dev)
services:
  api:
    volumes:
      - ./src:/app/src  # Hot-reload local
    environment:
      - NODE_ENV=development
Lancement avec fusion des deux fichiers (-f)
# Dev : Fusionne les deux, le .dev.yml écrase les clés communes
docker compose -f docker-compose.yml -f docker-compose.dev.yml up -d

# Prod : On utilise uniquement le fichier de base (pas de volume dev exposé !)
docker compose up -d