Introduction
Docker Compose simplifie le développement multi-conteneurs, mais les déploiements en production exigent plus qu’un simple docker compose up fonctionnel. Un fichier Compose mal configuré, une mauvaise correspondance de volumes ou une gestion des secrets non sécurisée peuvent provoquer des pannes, des pertes de données ou des failles de sécurité. Ce guide aborde les erreurs courantes de configuration de Docker Compose en production, avec des exemples pratiques et des étapes de récupération.
Vous apprendrez à identifier les problèmes de version et d’environnement, à valider les configurations avant le déploiement, à diagnostiquer les échecs et à effectuer un retour en arrière en toute sécurité. Chaque section comprend des commandes concrètes, les sorties attendues et les signaux d’échec pour vous aider à passer du problème observé au résultat vérifié.
L’objectif est la sécurité opérationnelle : observer avant de modifier, limiter le rayon d’impact, utiliser des variables d’environnement plutôt que des secrets en clair, vérifier le résultat et documenter les procédures de récupération avant qu’un incident ne force une décision précipitée.
Inventaire des versions et de l’environnement
Avant toute modification, établissez précisément ce que vous exécutez. Un incident de production provient souvent d’une inadéquation entre le format du fichier Compose, le moteur Docker et la version du plugin Docker Compose. Vérifiez d’abord les versions installées :
docker --version
# Docker version 24.0.7, build afdd53b
docker compose version
# Docker Compose version v2.23.0-desktop.1
Si votre fichier Compose spécifie une clé version:, assurez-vous qu’elle est compatible avec votre plugin Compose. Depuis Compose v2, la clé version est obsolète et ignorée, mais la supprimer peut perturber les outils plus anciens. Maintenez le format de fichier à jour en utilisant le schéma le plus récent sans clé de version, sauf si vous devez prendre en charge des systèmes hérités.
Ensuite, faites l’inventaire des conteneurs en cours d’exécution et de leur état de santé :
docker compose ps
# NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
# myapp-web-1 myapp/web:1.2.0 "nginx -g 'daemon of…" web 2 hours ago Up 2 hours 0.0.0.0:8080->80/tcp
# myapp-db-1 postgres:16.1 "docker-entrypoint.s…" db 2 hours ago Up 2 hours 5432/tcp
Si un conteneur est en mauvaise santé ou redémarre, inspectez-le. Utilisez le champ de statut de santé intégré de Docker pour un aperçu rapide, puis vérifiez le nombre de redémarrages séparément :
docker ps --filter name=myapp-web-1 --format '{{.Names}} {{.HealthStatus}}'
# myapp-web-1 healthy
docker inspect myapp-web-1 --format '{{.State.RestartCount}}'
# 0
Capturez les journaux pour identifier les erreurs :
docker compose logs web --tail 100
Vérification de la persistance des données
Une erreur courante en production est de stocker les données applicatives dans le système de fichiers du conteneur. Lorsque le conteneur est recréé, les données sont perdues. Confirmez toujours où vivent les données :
services:
db:
image: postgres:16.1
volumes:
- db_data:/var/lib/postgresql/data
volumes:
db_data:
Ici, db_data est un volume nommé géré par Docker. Il persiste à travers les reconstructions de conteneurs. Alternativement, un montage de type bind ./data:/var/lib/postgresql/data mappe un répertoire hôte mais peut introduire des problèmes de permissions et de portabilité.
Testez la persistance avec un redémarrage :
docker compose stop db
docker compose up -d db
docker compose exec db ls /var/lib/postgresql/data
# Si le répertoire est vide ou ne contient pas les fichiers attendus, les données n’ont pas été persistées correctement.
Chemin de configuration sécurisé
La configuration de production doit être délibérée, versionnée et révisable. Évitez de modifier directement docker-compose.yml sur le serveur. Utilisez plutôt des fichiers de surcharge spécifiques à l’environnement et des variables d’environnement pour les valeurs qui changent entre les environnements.
Utilisation des fichiers de surcharge
Une erreur courante consiste à maintenir plusieurs fichiers Compose presque identiques ou à coder en dur les valeurs de production dans le fichier de base. Utilisez un fichier de base avec des surcharges :
# docker-compose.yml
services:
web:
image: nginx:1.25
ports:
- "80:80"
environment:
- LOG_LEVEL=info
# docker-compose.prod.yml
services:
web:
environment:
- LOG_LEVEL=warn
- VIRTUAL_HOST=example.com
deploy:
replicas: 3
Déployez avec :
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
Cela garde le fichier de base propre et les paramètres spécifiques à la production séparés.
Variables d’environnement et secrets
Ne codez jamais en dur des secrets comme les mots de passe de base de données ou les clés API dans le fichier Compose, même s’il est dans un dépôt privé. Utilisez des variables d’environnement avec un fichier .env exclu du contrôle de version :
services:
db:
image: postgres:16.1
environment:
POSTGRES_PASSWORD: ${DB_PASSWORD}
Créez un fichier .env (assurez-vous qu’il est dans .gitignore) :
DB_PASSWORD=strongpassword123
Pour des données plus sensibles, utilisez Docker secrets (en mode Swarm) ou des gestionnaires de secrets externes. Au minimum, évitez d’imprimer les variables d’environnement dans les journaux :
docker compose exec db env
# Cela affichera toutes les variables d’environnement, y compris les secrets. À éviter en production.
Limites de ressources
Sans limites de ressources, un conteneur peut épuiser les ressources de l’hôte et affecter les autres services. Définissez des limites dans Compose :
services:
web:
image: nginx:1.25
deploy:
resources:
limits:
cpus: '0.50'
memory: 256M
reservations:
cpus: '0.25'
memory: 128M
Notez que deploy.resources est ignoré par docker compose up et n’est appliqué qu’en mode Swarm (docker stack deploy). Pour Compose non-Swarm, utilisez les clés mem_limit et cpus (obsolètes mais toujours fonctionnelles) ou comptez sur une orchestration externe.
Vérification et diagnostic
Après le déploiement, vérifiez que l’application fonctionne réellement, pas seulement que les conteneurs tournent.
Contrôles de santé
Définissez des contrôles de santé pour les services à longue durée de vie afin que Docker puisse les marquer comme défaillants :
services:
web:
image: nginx:1.25
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost"]
interval: 10s
timeout: 5s
retries: 3
start_period: 30s
Vérifiez le statut :
docker compose ps
# NAME STATUS
# myapp-web-1 Up 30 seconds (healthy)
Si un conteneur est en mauvaise santé, inspectez la sortie du contrôle de santé :
docker inspect --format '{{json .State.Health}}' myapp-web-1 | jq
Test de connectivité réseau
Les conteneurs sur le même réseau Compose peuvent se joindre par nom de service. Vérifiez la connectivité depuis un conteneur :
docker compose exec web curl http://db:5432
# Devrait retourner une réponse ou une connexion refusée si la base de données n’écoute pas.
Si le nom de service ne se résout pas, vérifiez que les deux conteneurs sont sur le même réseau :
docker network inspect myapp_default
Tous les services définis dans le même fichier Compose sont automatiquement sur le même réseau par défaut, sauf indication contraire.
Analyse des journaux
Utilisez les journaux pour diagnostiquer les problèmes. Pour un service spécifique :
docker compose logs db --since 10m
Pour le dépannage, vous pouvez vous attacher à un conteneur :
docker compose exec web sh
À l’intérieur, exécutez des commandes de diagnostic comme curl, ping, ou env (mais évitez d’exposer des secrets).
Modes de défaillance et récupération
Les erreurs arrivent ; planifiez la récupération avant d’en avoir besoin.
Retour en arrière de la configuration
Si un nouveau déploiement introduit un problème, le retour en arrière le plus rapide consiste à revenir à la version précédente du fichier Compose et à redéployer :
# En supposant que vous avez la version précédente dans git
git checkout <previous-commit> -- docker-compose.yml docker-compose.prod.yml
docker compose up -d --force-recreate
Alternativement, si vous utilisez des images taguées, revenez à l’étiquette d’image précédente :
services:
web:
image: nginx:1.24 # version précédemment fonctionnelle
Puis exécutez docker compose up -d.
Récupération des données
Si les données sont perdues ou corrompues, restaurez à partir des sauvegardes. Assurez-vous d’avoir des sauvegardes automatisées pour les volumes. Pour un volume nommé, vous pouvez le sauvegarder à l’aide d’un conteneur temporaire :
docker run --rm -v db_data:/data -v $(pwd):/backup alpine tar czf /backup/db_data_backup.tar.gz -C /data .
Restaurez :
docker run --rm -v db_data:/data -v $(pwd):/backup alpine sh -c "cd /data && tar xzf /backup/db_data_backup.tar.gz"
Testez régulièrement les restaurations.
Pièges courants et comment les éviter
Voici les erreurs fréquentes de Docker Compose en production, leurs causes et les stratégies de récupération.
| Erreur | Pourquoi cela arrive | Comment éviter ou récupérer |
|---|---|---|
Utiliser l’étiquette d’image latest en production | Suppose que la dernière version est stable ; peut introduire des changements cassants de façon inattendue | Épinglez les étiquettes d’image à des versions spécifiques ou des empreintes ; utilisez docker compose pull seulement après des tests |
| Exposer des ports de débogage (par exemple 5432 pour PostgreSQL) sur internet | Mauvaise configuration du mappage ports | Liez les ports à localhost uniquement : 127.0.0.1:5432:5432 |
Stocker des secrets en texte clair dans le fichier Compose ou .env commité dans git | Commodité, manque de gestion des secrets | Utilisez Docker secrets, des coffres-forts externes, ou au moins .env avec des permissions restreintes |
Exécuter avec privileged: true ou des capacités inutiles | Mauvaise compréhension des exigences de sécurité | Évitez le mode privilégié ; n’ajoutez que les capacités requises avec cap_add |
Ignorer la politique restart: always | Les conteneurs sortent sur erreur mais ne sont pas redémarrés | Définissez des politiques de redémarrage appropriées : restart: unless-stopped pour les services qui doivent toujours fonctionner |
| Ne pas définir de limites de ressources | Un conteneur peut consommer tout le CPU/mémoire | Définissez deploy.resources.limits (Swarm) ou mem_limit/cpus (Compose) |
Utiliser docker compose down sans l’option -v pendant le débogage | down supprime les conteneurs et réseaux mais pas les volumes par défaut ; supprimer manuellement les volumes entraîne une perte de données | Spécifiez toujours -v uniquement lorsque vous avez l’intention de supprimer les volumes ; sauvegardez d’abord |
| Écraser des fichiers hôtes avec des montages bind | Des erreurs de chemin de montage bind peuvent écraser des répertoires hôtes | Utilisez des volumes nommés pour la persistance, des montages bind uniquement pour le code/config que vous partagez intentionnellement |
Liste de vérification des opérations
Utilisez cette liste avant et après chaque déploiement en production pour détecter les erreurs courantes.
Avant le déploiement :
- [ ] Vérifiez les versions de Docker et Compose :
docker version && docker compose version - [ ] Exécutez
docker compose configpour valider la syntaxe du fichier Compose et fusionner les surcharges - [ ] Vérifiez les secrets codés en dur ; remplacez-les par des variables d’environnement ou des secrets
- [ ] Confirmez que les étiquettes d’image sont épinglées (pas
latest) - [ ] Révisez les montages de volumes et assurez-vous que les chemins de persistance des données sont corrects
- [ ] Définissez des limites de ressources pour chaque service
- [ ] Définissez des contrôles de santé pour les services critiques
- [ ] Sauvegardez les données existantes (surtout si vous modifiez des volumes)
- [ ] Ayez un plan de retour en arrière (étiquette d’image précédente ou version du fichier Compose)
Après le déploiement :
- [ ] Exécutez
docker compose pset confirmez que tous les services sont opérationnels et en bonne santé - [ ] Vérifiez les journaux :
docker compose logs --tail=200 - [ ] Vérifiez la fonctionnalité de l’application depuis un point de terminaison externe (le cas échéant)
- [ ] Surveillez l’utilisation des ressources :
docker stats - [ ] Confirmez qu’aucun port inattendu n’est exposé :
docker port <container> - [ ] Testez un redémarrage de conteneur pour vous assurer de la persistance des données :
docker compose restart <service> - [ ] Documentez tout écart et mettez à jour les procédures
Responsabilité et cadence de révision
Pour chaque décision majeure (par exemple, promotion d’étiquette d’image, rotation des secrets, changement de limites de ressources), assignez un responsable unique. Par exemple :
- Promotion d’étiquette d’image : Priya Shah, responsable ingénierie - révisée chaque semaine
- Rotation des secrets : John Doe, membre de l’équipe DevOps - révisée chaque mois
- Ajustements des limites de ressources : Maria Garcia, ingénieure infrastructure - révisés chaque trimestre
Ces responsables sont chargés de vérifier le changement et de mettre à jour la documentation.
Conclusion
Éviter les erreurs de configuration de Docker Compose en production exige une approche disciplinée : comprendre votre environnement, utiliser des pratiques de configuration sûres, vérifier rigoureusement et planifier la récupération. Les commandes et exemples de ce guide constituent un point de départ pour construire des déploiements résilients.
Commencez par appliquer une seule pratique, comme l’épinglage des étiquettes d’image ou l’ajout de contrôles de santé, et observez l’impact. Ensuite, élargissez à une liste de vérification complète du déploiement. Rappelez-vous que la sécurité en production repose sur l’observabilité, le principe du moindre privilège et des procédures de retour en arrière documentées.
Avec ces outils, vous pouvez déployer en toute confiance et récupérer rapidement lorsque les choses tournent mal.