Intro
Les profils Docker Compose, les fichiers d'override et la priorité des variables d'environnement sont essentiels car les conteneurs de production sont faciles à démarrer, mais beaucoup plus difficiles à exploiter de manière cohérente. Un guide technique utile montre quoi configurer, quelle commande prouve que la configuration fonctionne et à quoi ressemble un échec lorsque la configuration est incorrecte.
Ce guide explique comment les profils Docker Compose, les fichiers d'override, les valeurs env_file et la priorité du fichier .env interagissent afin que les équipes évitent la dérive de configuration entre les environnements local et de staging. Vous apprendrez l'ordre exact de priorité, verrez des structures de fichiers concrètes et exécuterez des commandes de vérification qui révèlent les mauvaises configurations avant qu'elles n'atteignent le CI/CD.
L'objectif est pratique : comprendre les éléments mobiles, les tester localement et éviter les surprises lorsque le même schéma est réutilisé dans des environnements proches de la production.
Workflow Overview
Docker Compose évalue la configuration dans un ordre précis. Comprendre cette chaîne de priorité est la base de déploiements multi‑environnements prévisibles.
Ordre de priorité (le plus fort l'emporte) :
- Drapeaux de ligne de commande (
-f,--profile,-e) docker-compose.override.yml(ou fichiers passés via-faprès le fichier de base)docker-compose.ymlde base- Fichier
.envdans le répertoire du projet - Variables d'environnement du shell
- Entrées
env_filedans le fichier compose (traitées par service, de haut en bas) - Clés
environment:dans le fichier compose - Instructions
ENVdu Dockerfile
Exemple concret : si POSTGRES_PASSWORD=secret est défini dans .env, remplacé par POSTGRES_PASSWORD=staging123 dans docker-compose.staging.yml et que le shell exporte POSTGRES_PASSWORD=prod456, le conteneur reçoit prod456 — l'environnement du shell gagne.
Les profils permettent d'activer des services optionnels sans modifier les fichiers. Définissez un profil dans le service :
services:
debug-tools:
image: busybox
profiles: [debug]
command: sleep infinity
Démarrez-le avec docker compose --profile debug up -d. Sans le drapeau, le service est ignoré entièrement — utile pour les sidecars, les exécuteurs de migrations ou les outils locaux uniquement.
Les fichiers d'override se superposent au fichier de base. Une disposition typique :
project/
├── docker-compose.yml # base : image, ports, volumes, réseaux
├── docker-compose.override.yml # développement local : bind mounts, ports de débogage, pas de limites de ressources
├── docker-compose.staging.yml # staging : limites de ressources, healthchecks, pas de bind mounts
└── .env # valeurs par défaut partagées : COMPOSE_PROJECT_NAME, TAG=latest
Exécutez le staging avec docker compose -f docker-compose.yml -f docker-compose.staging.yml up -d. Le fichier d'override est chargé automatiquement sauf si vous le désactivez en listant explicitement les fichiers (les fichiers explicites suppriment l'override automatique).
Commandes de vérification pratiques :
# Afficher la configuration effective après toutes les fusions
docker compose config
# Afficher la configuration pour un profil spécifique
docker compose --profile debug config
# Vérifier quelles valeurs de fichier d'env sont réellement parvenues dans le conteneur
docker compose exec app env | grep POSTGRES
# Inspecter la définition de service fusionnée
docker compose config --services
Local Pilot Plan
Appliquez les règles de priorité dans un test local contrôlé avant de promouvoir vers les environnements partagés.
Étape 1 : Créer le fichier de base (docker-compose.yml) :
services:
api:
image: myapp:${TAG:-latest}
ports:
- "8000:8000"
environment:
- APP_ENV=production
- LOG_LEVEL=info
env_file:
- .env.api
deploy:
resources:
limits:
memory: 512M
Étape 2 : Créer .env à la racine du projet (valeurs par défaut partagées) :
TAG=v1.2.3
COMPOSE_PROJECT_NAME=myapp
Étape 3 : Créer le fichier d'env spécifique au service (.env.api) :
DATABASE_URL=postgres://user:pass@db:5432/app
REDIS_URL=redis://redis:6379/0
Étape 4 : Créer l'override local (docker-compose.override.yml) :
services:
api:
build:
context: .
dockerfile: Dockerfile.dev
volumes:
- ./src:/app/src:ro
environment:
- LOG_LEVEL=debug
ports:
- "9229:9229" # inspecteur Node
profiles:
- dev-tools
mailcatcher:
image: schickling/mailcatcher
ports:
- "1080:1080"
profiles:
- dev-tools
Étape 5 : Créer l'override staging (docker-compose.staging.yml) :
services:
api:
image: myapp:${TAG}
environment:
- APP_ENV=staging
- LOG_LEVEL=warn
healthcheck:
test: ["CMD", "wget", "-q", "--spider", "http://localhost:8000/health" ]
interval: 30s
timeout: 10s
retries: 3
deploy:
resources:
limits:
memory: 1G
cpus: '0.5'
db:
image: postgres:15
volumes:
- pgdata:/var/lib/postgresql/data
environment:
- POSTGRES_PASSWORD_FILE=/run/secrets/db_password
secrets:
- db_password
volumes:
pgdata:
secrets:
db_password:
external: true
Étape 6 : Tester localement avec le profil dev
# Démarre api + mailcatcher, utilise bind mounts, logging debug
docker compose --profile dev-tools up -d
# Vérifier la configuration fusionnée
docker compose --profile dev-tools config | head -80
# Contrôler l'environnement à l'intérieur du conteneur
docker compose exec api env | sort
Étape 7 : Simuler le staging localement
# Fichiers explicites suppriment l'override.yml automatique
docker compose -f docker-compose.yml -f docker-compose.staging.yml up -d
# Vérifier l'absence de bind mounts, présence du healthcheck, limites de ressources appliquées
docker compose -f docker-compose.yml -f docker-compose.staging.yml config
# Confirmer que les secrets sont montés (nécessite la configuration Docker secrets)
docker compose -f docker-compose.yml -f docker-compose.staging.yml exec api ls -la /run/secrets/
Étape 8 : Test de redémarrage — arrêter et recréer, confirmer la persistance des données :
docker compose -f docker-compose.yml -f docker-compose.staging.yml down
docker compose -f docker-compose.yml -f docker-compose.staging.yml up -d
docker compose -f docker-compose.yml -f docker-compose.staging.yml exec db psql -U postgres -c "SELECT 1;"
Si la connexion à la base de données échoue ou que les données manquent, le volume n'a pas été déclaré correctement ou le conteneur a écrit dans son système de fichiers au lieu du volume nommé.
Conclusion
Les profils Docker Compose, les fichiers d'override et la priorité des variables d'environnement fonctionnent le mieux lorsque l'équipe traite la configuration comme quelque chose à tester, et non seulement à copier. La voie la plus sûre consiste à garder les exemples simples, à exécuter les commandes de vérification localement et à confirmer le comportement attendu avant d'ajouter davantage de services ou d'automatisation.
Pour une prochaine étape, choisissez un service et documentez les commandes exactes utilisées pour construire, exécuter, inspecter, arrêter et recréer ce service dans chaque fichier d'environnement. Comparez ensuite le résultat avec des domaines connexes tels que Docker Compose, les workflows locaux proches de la production et la configuration Docker afin que l'implémentation s'intègre au modèle d'exploitation global.
Un workflow de conteneurs fiable rend l'échec visible : les logs sont faciles à trouver, les données persistantes survivent aux reconstructions de conteneurs, et le comportement local est suffisamment proche de la production pour détecter les erreurs tôt.