Docker Compose : guide multi-conteneurs
Docker Compose orchestre plusieurs conteneurs avec un fichier lisible : services, réseau, volumes, secrets, santé et diagnostic sans perte de données.
Serveurs dédiés, infogérance et migration
Il couvre les serveurs dédiés, l'infogérance, le stockage, la supervision et les plans de sortie.
Docker Compose décrit une application composée de plusieurs conteneurs dans un fichier compose.yaml, puis les crée, les relie et les arrête comme un ensemble. Pour un déploiement fiable, séparez les services, persistez les données, attendez les contrôles de santé et validez la configuration avant chaque démarrage.
Sur un serveur comme dans un atelier, ranger les outils ne les rend pas infaillibles. Compose rend leurs relations explicites : image ou construction locale, réseau, volume, configuration, secret et ordre de démarrage. Cette lisibilité permet de relire l’application avant de la lancer et de comprendre ce qui survivra à son arrêt.
Ce guide construit un exemple générique avec une application et une base de données. Adaptez les noms de variables à votre logiciel : une image n’accepte pas magiquement les paramètres montrés ici. Commencez par le contrat de l’image, puis écrivez le fichier Compose qui le respecte.
Docker Compose est un contrat d’application
Le fichier compose.yaml décrit l’état attendu. La section services contient les composants exécutables. Les sections volumes, networks et secrets déclarent des ressources partagées ou contrôlées. La spécification Compose actuelle est la référence ; ajouter une ancienne clé version n’améliore pas la compatibilité et détourne l’attention du modèle réellement appliqué.
Un service n’est pas un serveur miniature. C’est une définition à partir de laquelle Compose crée un conteneur. Deux services qui partagent un réseau peuvent se joindre par leur nom de service. Ils n’ont pas besoin de connaître une adresse IP de conteneur, car cette adresse peut changer lors d’une recréation.
Avant d’écrire le YAML, dressez cet inventaire :
- processus : application, base, cache, proxy ou tâche ponctuelle ;
- données durables : répertoires qui doivent survivre au conteneur ;
- flux réseau : communications internes et ports réellement publics ;
- configuration : valeurs non sensibles qui changent selon l’environnement ;
- secrets : mots de passe, clés et certificats à distribuer au strict nécessaire ;
- signal de disponibilité : test qui prouve que chaque dépendance répond vraiment.
Si cet inventaire reste flou, le fichier sera seulement une collection de commandes déplacée en YAML.
Construire un fichier multi-services lisible
L’exemple suivant sépare une application construite localement d’une base PostgreSQL. Le réseau front reçoit l’application, tandis que le réseau back relie l’application à la base. Le volume db-data conserve les données. Le secret db-password est accordé aux deux services parce que chacun doit lire le même mot de passe.
name: atelier
services:
app:
build: ./app
ports:
- "127.0.0.1:8080:8080"
environment:
DATABASE_HOST: db
DATABASE_NAME: app
DATABASE_USER: app
DATABASE_PASSWORD_FILE: /run/secrets/db-password
secrets:
- db-password
depends_on:
db:
condition: service_healthy
restart: true
networks:
- front
- back
db:
image: postgres:alpine
environment:
POSTGRES_DB: app
POSTGRES_USER: app
POSTGRES_PASSWORD_FILE: /run/secrets/db-password
secrets:
- db-password
healthcheck:
test: ["CMD-SHELL", "pg_isready -U app -d app"]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
volumes:
- db-data:/var/lib/postgresql/data
networks:
- back
networks:
front:
back:
internal: true
volumes:
db-data:
secrets:
db-password:
file: ./secrets/db-password.txt
Ne copiez pas cet exemple sans vérifier l’image. Le suffixe de variable FILE est une convention acceptée par certaines images officielles, pas une capacité universelle. Votre application locale doit elle aussi savoir lire le fichier indiqué. Sinon, adaptez son point d’entrée sans remettre le secret en clair dans le YAML.
Le fichier de secret reste sur l’hôte. Excluez-le du gestionnaire de versions, limitez ses permissions et prévoyez sa sauvegarde séparée. Compose le monte dans les services autorisés sous le répertoire des secrets ; il ne devient pas pour autant un coffre-fort distant ni un système de rotation.
Réseau : publier uniquement ce qui doit sortir
Le nom db est l’adresse stable dans le projet. L’application contacte la base avec ce nom sur le réseau back. Publier le port PostgreSQL sur l’hôte serait inutile pour ce trajet et augmenterait la surface exposée.
La liaison du port applicatif commence par l’adresse loopback de l’hôte. Elle rend le service accessible depuis la machine, mais pas directement depuis toutes ses interfaces. Un proxy installé sur l’hôte peut alors le publier avec TLS et les règles d’accès adaptées.
Si le proxy tourne lui-même dans Compose, placez-le sur le réseau front et retirez le port hôte de l’application. Le trafic reste ainsi dans le réseau du projet jusqu’au composant chargé de l’exposition publique.
Un port écrit seulement sous la forme hôte:conteneur est généralement lié à toutes les interfaces de la machine. Vérifiez l’adresse de liaison, pas seulement le numéro. Sur un VPS doté d’une adresse publique, une omission devient vite une exposition réelle.
Les réseaux explicites servent aussi de cloison. Le service db ne rejoint pas front ; un composant attaché uniquement à front ne peut donc pas le contacter. Cette séparation ne remplace ni l’authentification ni le pare-feu, mais elle évite les chemins réseau gratuits.
Dépendances : démarré ne veut pas dire prêt
depends_on organise la création, pas la disponibilité métier. Sans condition de santé, Compose sait qu’un conteneur de base a démarré, pas qu’il accepte déjà des connexions. Une application rapide peut tenter sa première connexion pendant l’initialisation de PostgreSQL et échouer alors que les deux conteneurs paraissent actifs.
Le healthcheck de l’exemple interroge PostgreSQL avec son propre outil. La condition service_healthy demande à Compose d’attendre ce verdict avant de créer l’application. Les temporisations sont des valeurs de départ, pas des constantes sacrées. Ajustez-les à la durée réelle d’initialisation et au coût du test.
Gardez aussi une stratégie de reconnexion dans l’application. Un contrôle de santé règle la course au premier démarrage ; il ne garantit pas qu’une dépendance restera disponible. Une base peut redémarrer plus tard, un réseau peut être brièvement indisponible et une opération de maintenance peut recréer le conteneur.
La directive restart placée dans la dépendance de l’exemple concerne les redémarrages explicites effectués par Compose. Elle aide l’application à rétablir sa connexion après une opération contrôlée. Elle ne remplace ni une politique de redémarrage du conteneur ni le traitement des erreurs dans le code.
Données, configuration et secrets
Ces trois mécanismes répondent à des besoins différents :
| Besoin | Mécanisme | Contrôle indispensable |
|---|---|---|
| Conserver l’état de la base | Volume nommé | Sauvegarde et restauration testée |
| Régler un comportement non sensible | environment ou env_file | Valeur finale après interpolation |
| Fournir un mot de passe ou une clé | Secret accordé au service | Permissions, rotation et absence des journaux |
| Monter du code local en développement | Bind mount | Propriétaire, droits et impact sur l’image |
Un volume n’est pas une sauvegarde. Il survit à la recréation d’un conteneur, mais reste lié au moteur Docker et au stockage de l’hôte. Le disque décide souvent au pire moment : exportez les données avec l’outil de la base et testez la restauration ailleurs.
Le fichier .env sert d’abord à l’interpolation du modèle Compose. La section env_file ou environment peuple l’environnement du conteneur. Ces chemins se ressemblent assez pour provoquer des erreurs de priorité. Affichez le modèle résolu avant le démarrage et n’utilisez pas l’environnement pour dissimuler un secret : il peut apparaître dans un diagnostic ou un journal.
Valider, démarrer et diagnostiquer
Validez avant de modifier l’hôte. La commande config résout les variables, fusionne les fichiers éventuels et rend le modèle canonique. Son mode silencieux permet un contrôle simple dans une intégration continue.
docker compose config
docker compose config --quiet
Relisez particulièrement les ports, les chemins, les noms d’images et les variables vides. Une configuration valide syntaxiquement peut rester dangereuse opérationnellement.
Démarrez ensuite le projet, puis observez son état avant de conclure :
docker compose up -d --build
docker compose ps
docker compose logs --tail 100 app db
Si un service échoue, réduisez le diagnostic à sa frontière :
docker compose logs app
docker compose logs db
docker compose exec app getent hosts db
docker compose config --environment
La résolution du nom db confirme le chemin réseau, pas la disponibilité de PostgreSQL. Les journaux de la base et son état de santé complètent le diagnostic. Demandez le plan de panne : quel signal distingue une erreur de configuration, une dépendance indisponible et une donnée corrompue ?
Arrêter sans effacer les données
La commande suivante arrête le projet et supprime ses conteneurs ainsi que les réseaux créés pour lui. Les volumes nommés restent présents.
docker compose down
L’option qui ajoute la suppression des volumes change complètement le niveau de risque. Elle convient à un environnement jetable dont les données peuvent être recréées, pas à une base que personne n’a sauvegardée.
docker compose down --volumes
Avant cette commande, listez les volumes du projet, identifiez leur contenu et restaurez une sauvegarde sur une autre cible. La persistance doit avoir un chemin d’entrée, mais aussi un chemin de sortie. La migration fait partie du coût, même pour une petite pile auto-hébergée.
Quand choisir ou éviter Docker Compose
| Situation | Compose convient | Réserve à traiter |
|---|---|---|
| Développement local multi-services | Oui | Alignement avec l’environnement cible |
| Application sur un seul hôte administré | Oui | Sauvegardes, supervision et procédure de retour |
| Petit service interne stable | Oui | Mises à jour d’images et exposition réseau |
| Répartition automatique sur plusieurs hôtes | Non | Utiliser un orchestrateur conçu pour ce rôle |
| Déploiement sans interruption exigé | Pas seul | Prévoir proxy, stratégie de bascule et supervision |
| Équipe sans propriétaire opérationnel | Non | Choisir un service géré ou attribuer l’exploitation |
Compose est un bon choix quand la limite de l’application tient sur un hôte et dans un fichier que l’équipe sait relire. Il devient un mauvais alibi quand personne ne possède les sauvegardes, les alertes ou la procédure de mise à jour.
Liste de contrôle
- Vérifiez le modèle résolu et bloquez toute variable vide, tout port public inattendu ou tout chemin absent.
- Contrôlez chaque dépendance avec un test de santé qui mesure la disponibilité utile, pas seulement un processus actif.
- Restaurez le volume de données sur une cible distincte afin de mesurer le risque réel avant une mise à jour.
- Documentez l’arrêt, la recréation et le retour arrière avant de confier le projet à une exploitation régulière.
Questions fréquentes
Faut-il ajouter une clé version dans compose.yaml ?
Comment deux services Compose communiquent-ils ?
depends_on suffit-il pour attendre une base de données ?
Un fichier .env protège-t-il les mots de passe ?
Préparé par
Serveurs dédiés, infogérance et migration
Il couvre les serveurs dédiés, l'infogérance, le stockage, la supervision et les plans de sortie.
Faits vérifiés
HostScout editorialArticles liés
Clés SSH : l’authentification sans mot de passe
Créer une clé SSH Ed25519, installer la clé publique, vérifier l’hôte et désactiver le mot de passe sans perdre l’accès.
Installer Zabbix pour superviser ses serveurs
Installer Zabbix 7.0 LTS sur Ubuntu 24.04 avec PostgreSQL, Nginx et Agent 2, puis sécuriser et valider chaque composant.
MySQL : créer un utilisateur et gérer les droits
Créer un utilisateur MySQL 8.4, limiter son hôte, attribuer puis retirer des droits, imposer TLS et contrôler le résultat.
NGINX reverse proxy : exposer plusieurs services
NGINX reverse proxy pour plusieurs services : chemins proxy_pass, en-têtes fiables, WebSocket, frontière TLS et diagnostic avant rechargement.
Installer Docker sur Ubuntu et Debian
Installer Docker sur Ubuntu et Debian via le dépôt officiel, vérifier Engine et Compose, puis sécuriser les droits et les ports publiés.
Adresse IP publique ou privée : la repérer
Adresse IP publique ou privée : comprenez ce qui vous identifie en ligne, où trouver chaque adresse et quoi vérifier avant d'exposer un serveur.