E-NO Logo
EN FR
Docker Compose advanced concepts 9 Min Read

Docker Compose : concepts avancés expliqués avec des exemples pratiques

calendar_today Published: 2026-07-14
update Last Updated: 2026-07-14
analytics SEO Efficiency: 100%
Technical guide illustration for Docker Compose : concepts avancés expliqués avec des exemples pratiques.

Introduction

Les Docker Compose advanced concepts ne consistent pas à « ajouter des conteneurs », mais à maîtriser comment un ensemble de services est construit, démarré, découvert, configuré, sécurisé et observé comme une seule unité. Dans ce guide, vous allez :

  • Comprendre les Docker Compose internals pour anticiper le comportement.
  • Appliquer des fonctionnalités avancées : profils, healthchecks avec dépendances conditionnelles, secrets et configs, anchors YAML, et superposition multi-fichiers.
  • Lancer un pilote local ciblé qui prouve la valeur sans risque pour la production.

Ce texte sert de Docker Compose deep dive pragmatique, avec des Docker Compose examples directement utilisables et une vue claire de la Docker Compose architecture côté hôte.

Vue d'ensemble du flux de travail

Utilisez cette séquence pour introduire les fonctionnalités de Compose en sécurité :

  1. Concevoir le graphe de services
  • Définissez services, frontières de données et ports exposés. Choisissez des volumes nommés pour l'état.
  1. Construire
  • Utilisez build context, multi-stage targets et build args. Préférez BuildKit avec transfert SSH si vous récupérez des dépendances privées.
  1. Exécuter
  • Démarrez avec un nom de projet, des profils pour les outils facultatifs et des healthchecks. Utilisez depends_on avec des conditions pour contrôler le démarrage.
  1. Observer
  • Streamez les logs, inspectez l'état de santé et interrogez les noms DNS des conteneurs sur le réseau du projet.
  1. Durcir
  • Ajoutez des systèmes de fichiers en lecture seule lorsque possible, définissez des ulimits et montez les secrets en fichiers. Évitez deploy.* sauf en mode Swarm.

Internes de Compose qui comptent

Ces détails éliminent la plupart des surprises :

  • Nom de projet
  • Compose regroupe tout par un nom de projet (top-level name: ou -p côté CLI). Réseaux et volumes sont créés avec ce préfixe, isolant les services entre projets sur le même hôte.
  • Réseau par défaut
  • Compose crée un réseau bridge défini par l'utilisateur, par projet. Chaque nom de service devient un hostname DNS sur ce réseau (par exemple, db résout vers le conteneur Postgres). Pas besoin de links.
  • Fusion de fichiers
  • Plusieurs fichiers -f sont fusionnés de haut en bas. Les derniers écrasent/étendent les premiers. Maintenez un fichier de base stable et superposez des changements spécifiques à l'environnement.
  • Résolution des variables d'environnement
  • Compose supporte ${VAR} et ${VAR:-default} dans le YAML. Il lit .env dans le répertoire du projet et l'environnement shell courant. Les variables du shell priment sur .env. env_file au niveau service injecte des variables dans ce conteneur, sans affecter la substitution au niveau Compose.
  • Ordre de démarrage et disponibilité
  • depends_on sans conditions ordonne le démarrage des conteneurs, pas leur « readiness ». Utilisez un healthcheck et depends_on avec condition: service_healthy pour attendre la disponibilité lorsque votre version de Compose le permet.
  • Statut de santé
  • Un service avec healthcheck rapporte healthy, starting ou unhealthy. Interrogez-le via docker compose ps et docker compose logs.
  • Clés spécifiques Swarm
  • Les clés sous deploy.* concernent Swarm. En exécution classique sur un seul hôte, Compose ignore l'essentiel. Utilisez les options de service (environment, volumes, ulimits, read_only, etc.) hors Swarm.

Concepts avancés avec exemples

Ci-dessous, un fichier de base « orienté production » montrant plusieurs schémas avancés. Il exécute un service web en frontal Nginx, Postgres et Redis. On y trouve profils, healthchecks, secrets, configs, champs d'extension et parades de sécurité.

# compose.yml
name: myapp

# Champs d'extension et ancres pour la réutilisation
x-service-defaults: &service_defaults
  restart: unless-stopped
  networks:
    - appnet
  env_file:
    - ./.env
  init: true

x-healthchecks:
  postgres: &pg_health
    test: ["CMD-SHELL", "pg_isready -U $POSTGRES_USER -d $POSTGRES_DB"]
    interval: 3s
    timeout: 3s
    retries: 10
  redis: &redis_health
    test: ["CMD", "redis-cli", "ping"]
    interval: 3s
    timeout: 3s
    retries: 10
  web: &web_health
    test: ["CMD", "wget", "-qO-", "http://localhost/healthz"]
    interval: 5s
    timeout: 3s
    retries: 10

services:
  db:
    <<: *service_defaults
    image: postgres:16
    environment:
      POSTGRES_DB: app
      POSTGRES_USER: app
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password
    volumes:
      - pgdata:/var/lib/postgresql/data
    healthcheck: *pg_health
    secrets:
      - db_password
    ulimits:
      nofile: 65535

  cache:
    <<: *service_defaults
    image: redis:7
    command: ["redis-server", "--appendonly", "yes"]
    volumes:
      - redisdata:/data
    healthcheck: *redis_health

  web:
    <<: *service_defaults
    build:
      context: ./web
      dockerfile: Dockerfile
      target: runtime
      args:
        APP_ENV: ${APP_ENV:-dev}
      ssh:
        - default
    depends_on:
      db:
        condition: service_healthy
      cache:
        condition: service_healthy
    ports:
      - "8080:80"
    healthcheck: *web_health
    read_only: true
    tmpfs:
      - /tmp
    security_opt:
      - no-new-privileges: true
    configs:
      - source: nginx_conf
        target: /etc/nginx/conf.d/app.conf

  adminer:
    <<: *service_defaults
    image: adminer:4
    profiles: ["tools"]
    ports:
      - "8081:8080"

configs:
  nginx_conf:
    file: ./deploy/nginx/app.conf

secrets:
  db_password:
    file: ./secrets/db_password.txt

networks:
  appnet: {}

volumes:
  pgdata: {}
  redisdata: {}

Points clés :

  • name: myapp fixe le nom de projet pour un préfixe réseau/volume stable.
  • Les ancres (x-service-defaults, x-healthchecks) réduisent la duplication.
  • Healthchecks + depends_on conditionnel bloquent le démarrage de web tant que Postgres et Redis ne sont pas prêts.
  • secrets et configs montent des fichiers dans les conteneurs ; protégez les permissions côté hôte.
  • read_only et no-new-privileges durcissent le conteneur web, et tmpfs pour /tmp évite les écritures sur l'image.
  • Les profiles activent des outils optionnels (ex. adminer) à la demande.

Surcharges locales pour itérer

Utilisez un second fichier pour monter le code source et activer des flags de debug, sans toucher au fichier de base.

# compose.override.yml (pris en charge automatiquement par docker compose)
services:
  web:
    volumes:
      - ./web/src:/var/www/src: rw, cached
    environment:
      DEBUG: "1"

Pour des changements spécifiques à un environnement qui ne doivent pas être chargés automatiquement, créez un fichier distinct et passez-le explicitement.

# compose.prod.yml
services:
  web:
    environment:
      APP_ENV: prod
    ports:
      - "80:80"    # publier sur le port standard en prod
  adminer:
    profiles: ["never"]   # désactiver les outils en prod

Exécuter avec :

# Base + surcouche prod explicite
docker compose -f compose.yml -f compose.prod.yml up -d

Variables d'environnement et .env

Créez un fichier .env dans le répertoire du projet pour la substitution au niveau Compose et des valeurs communes :

# .env
APP_ENV=dev
POSTGRES_PASSWORD=unused_when_using_secret
# Vous avez toujours besoin de secrets/db_password.txt pour le secret fichier

Notes :

  • Les variables du shell priment sur .env pour la substitution. Exemple : APP_ENV=staging docker compose up utilisera staging.
  • env_file sous un service injecte des variables dans ce conteneur uniquement.

Multi-stage builds avec targets et SSH

Utilisez le multi-stage pour garder une image runtime petite et récupérer des dépendances privées de manière sécurisée.

# web/Dockerfile
FROM golang:1.22 AS build
WORKDIR /src
# optionnel : BuildKit SSH pour deps privées
# RUN --mount=type=ssh go env -w GOPRIVATE=github.com/yourorg/*
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o /out/app ./cmd/app

FROM nginx:1.27-alpine AS runtime
COPY --from=build /out/app /usr/local/bin/app
COPY deploy/nginx/app.conf /etc/nginx/conf.d/app.conf
# endpoint de santé simple
HEALTHCHECK --interval=5s --timeout=3s --retries=10 CMD wget -qO- http://localhost/healthz || exit 1

Utilisation de BuildKit :

# Activer BuildKit et l'agent SSH pour les dépôts privés
export DOCKER_BUILDKIT=1
export COMPOSE_DOCKER_CLI_BUILD=1
ssh-add -l >/dev/null 2>&1 || ssh-add
docker compose build --ssh default

Plan de pilote local

Démarrez par un pilote restreint, mesurable, qui exerce les fonctionnalités les plus utiles sans surcomplexité.

Objectifs du pilote :

  • Prouver que le démarrage dépend de la santé (web attend db et cache).
  • Valider les montages de secrets et configs.
  • Confirmer le périmètre de projet et la découverte de services via le réseau applicatif.

Préparation :

  1. Créez les répertoires et fichiers
mkdir -p deploy/nginx secrets web/src
printf 'server {\n  listen 80;\n  location /healthz { return 200 "ok"; }\n  location / { return 200 "hello"; }\n}\n' > deploy/nginx/app.conf
umask 077 && printf 'supersecretpassword\n' > secrets/db_password.txt
  1. Optionnel : ajoutez .env avec APP_ENV=dev

Exécuter le pilote :

# Lancer la pile de base et, si besoin, le profil d'outils
docker compose up -d --build
# ou inclure les outils
docker compose --profile tools up -d --build

Valider :

# Vérifier l'état et la santé des services
docker compose ps

# Attendre l'état healthy (versions récentes)
docker compose up --wait

# Taper l'endpoint web
curl -sS http://localhost:8080/healthz

# Valider la découverte DNS de web vers db
docker compose exec web getent hosts db

# Vérifier le montage des secrets dans db
docker compose exec db ls -l /run/secrets

Observer et itérer :

  • docker compose logs -f web db cache montre la séquence de démarrage.
  • Si les healthchecks échouent, inspectez les tests et les logs pour ajuster timings et commandes.

Nettoyer proprement :

docker compose down --volumes

Astuces pratiques et défauts sûrs

  • Utilisez des volumes nommés pour les bases de données ; évitez de binder un dossier de DB depuis l'hôte.
  • Conservez le réseau de projet par défaut. Publiez uniquement les ports nécessaires.
  • Préférez healthchecks + depends_on conditionnels aux scripts d'attente ad hoc.
  • Utilisez des profiles pour garder les outils facultatifs désactivés par défaut.
  • Évitez deploy.* si vous n'êtes pas en mode Swarm.
  • Traitez les secrets locaux comme sensibles : restreignez les permissions de ./secrets et ne les validez pas en VCS.
  • Fixez les tags d'images pour les services de base (ex. postgres:16) pour éviter les mises à jour surprises.

Conclusion

Vous disposez maintenant d'un modèle mental clair de la façon dont Docker Compose regroupe les services, câble le réseau et la découverte, résout la configuration et impose l'état de santé. Commencez par le pilote local pour valider le démarrage conditionné par la santé, les secrets et les configs. Ensuite, superposez des fichiers spécifiques d'environnement, durcissez avec des systèmes de fichiers en lecture seule et no-new-privileges, et gardez les outils optionnels derrière des profils. Cette approche progressive réduit les risques tout en tirant pleinement parti des Docker Compose advanced concepts, d'un Docker Compose deep dive pragmatique et de Docker Compose internals utiles au quotidien.

Article Quality Score

Reader usefulness 100%
  • check_circle Reader-ready guide
  • check_circle Practical examples included
  • check_circle Clean SEO article URL