infra / docker-compose
Override files : docker-compose.override.yml et fusion multi-fichiers
Explication
Ce que vous allez apprendre
- Comprendre pourquoi
docker-compose.override.ymlse charge automatiquement, sans rien préciser - Fusionner plusieurs fichiers Compose explicitement avec
-f fichier1.yml -f fichier2.yml - Prédire le résultat d'une fusion selon le type de valeur (scalaire, liste, map)
- Vérifier une configuration fusionnée avant un déploiement avec
docker compose config - Séparer proprement les réglages de développement local des réglages de production
Dans quel contexte ?
Sur le projet boutique-api, l'équipe veut que chaque développeur ait un bind mount vers son code source et un port de debug Node ouvert en local, sans que ces réglages n'apparaissent jamais en production, où l'on veut au contraire des limites de ressources strictes et un redémarrage automatique. Plutôt que deux fichiers Compose complets et redondants, cette leçon montre comment superposer des calques de configuration.
Le problème : base commune + variations
D'abord, un constat familier : un même projet a presque toujours une base commune (les images, les services, les réseaux) et des variations selon le contexte, comme des bind mounts en développement ou des limites de ressources en production.
Pourquoi tout réécrire serait une mauvaise idée
Réécrire l'intégralité du fichier pour chaque environnement serait source d'incohérences : un oubli dans un fichier, et la config diverge silencieusement de l'autre. Il faut un mécanisme pour ne modifier QUE ce qui change réellement.
L'idée : des calques superposés
Compose permet de fusionner plusieurs fichiers YAML les uns par-dessus les autres, un peu comme des calques en superposition. Chaque calque ajoute ou modifie certaines valeurs, sans dupliquer les autres.
Le fichier magique : override, chargé tout seul
Il existe un fichier particulier, docker-compose.override.yml. S'il existe à côté du fichier de base, il est fusionné AUTOMATIQUEMENT par un simple docker compose up, sans rien préciser en ligne de commande. C'est le fichier idéal pour les réglages spécifiques au développement local, comme les bind mounts ou les ports de debug.
Il reste une question : comment se passe la fusion ?
Une fois qu'on sait que deux fichiers peuvent définir la même clé, il faut comprendre ce qui se passe. Le comportement dépend du type de valeur : les valeurs simples (scalaires) sont remplacées par la dernière définition, les listes (comme ports) sont concaténées, et les objets (comme environment) sont fusionnés clé par clé.
| Type de valeur | Exemple de clé | Comportement à la fusion |
|---|---|---|
| Scalaire | restart, image | La dernière valeur définie remplace la précédente |
| Liste | ports, volumes | Les deux listes sont concaténées |
| Map | environment, labels | Fusion clé par clé, récursive |
Prérequis
Cette leçon suppose que tu es à l'aise avec la syntaxe de base d'un fichier docker-compose.yml (services, ports, environment), vue dans les toutes premières leçons de ce cours.
Le piège en production
Attention, en production, l'override.yml n'est JAMAIS chargé automatiquement. Il faut explicitement lister les fichiers avec l'option -f, dans l'ordre voulu, sinon la configuration de production risque de manquer des éléments essentiels.
Piège fréquent
Oublier docker-compose.prod.yml dans la commande -f fait démarrer la stack de production avec uniquement le fichier de base, sans les limites de ressources ni la politique de redémarrage prévues. Vérifie toujours la liste complète des fichiers -f avant de lancer un up en production.
Un dernier réflexe avant de déployer
Enfin, ne déploie jamais sans avoir vérifié le résultat de la fusion avec docker compose config. Cela évite de découvrir la configuration finale en production plutôt qu'avant, au moment où une erreur coûte le plus cher.
Maintenant que tu sais adapter une configuration par environnement, la leçon suivante explore un besoin complémentaire : faire tourner plusieurs instances identiques d'un même service, avec le scaling.
Commandes & code
Override files
Compose peut fusionner plusieurs fichiers YAML pour adapter la config par environnement, sans dupliquer la base commune.
# docker-compose.yml (base commune, versionnée dans le repo)
services:
api:
build: ./api
environment:
NODE_ENV: production
restart: unless-stopped
db:
image: postgres:16
environment:
POSTGRES_PASSWORD: changeme# docker-compose.override.yml (chargé AUTOMATIQUEMENT en dev, à côté du fichier de base)
services:
api:
build:
context: ./api
target: dev # stage de dev avec hot-reload
volumes:
- ./api/src:/app/src # bind mount pour le live reload
environment:
NODE_ENV: development
ports:
- "3000:3000"
- "9229:9229" # port de debug Node.js
command: ["npm", "run", "dev"]# docker-compose.prod.yml (chargé explicitement, JAMAIS auto)
services:
api:
restart: always
deploy:
resources:
limits:
cpus: "1.0"
memory: 512M
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"# En dev : "docker-compose.yml" + "docker-compose.override.yml" fusionnés automatiquement
docker compose up -d
# En prod : override.yml ignoré, on combine explicitement base + prod
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
# Vérifier le résultat de la fusion avant de déployer
docker compose -f docker-compose.yml -f docker-compose.prod.yml config# Règles de fusion : les scalaires sont écrasés, les listes sont concaténées,
# les maps sont fusionnées clé par clé (récursivement).
# Exemple : "ports" et "environment" s'additionnent, "restart" est remplacé.Résumé
docker-compose.override.ymlest fusionné automatiquement, pratique pour le dev local.-f a.yml -f b.ymlfusionne des fichiers explicites, dans l'ordre donné.- Les maps fusionnent clé par clé, les listes se concatènent, les scalaires s'écrasent.
- Toujours valider avec
docker compose ... configavant un déploiement.
Exercices pratiques
Mission : un déploiement de production incomplet et silencieux
Objectif : Prédire le résultat d'une fusion de fichiers Compose et diagnostiquer un -f manquant.
Contexte
docker-compose.yml (base) définit restart: unless-stopped pour api, tandis que docker-compose.prod.yml redéfinit restart: always. Ce jour-là, l'équipe déploie en production en oubliant docker-compose.prod.yml dans la commande -f, et la stack démarre quand même, sans aucune erreur visible.
Analyse ce qui se passe réellement dans chaque cas.