Retour au cours

infra / docker-compose

Override files : docker-compose.override.yml et fusion multi-fichiers

Leçon 91 exercice

Explication

Ce que vous allez apprendre

  • Comprendre pourquoi docker-compose.override.yml se 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 valeurExemple de cléComportement à la fusion
Scalairerestart, imageLa dernière valeur définie remplace la précédente
Listeports, volumesLes deux listes sont concaténées
Mapenvironment, labelsFusion 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.

yaml
# 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
yaml
# 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"]
yaml
# 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"
bash
# 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
yaml
# 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.yml est fusionné automatiquement, pratique pour le dev local.
  • -f a.yml -f b.yml fusionne 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 ... config avant un déploiement.

Exercices pratiques

1 disponible
1

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.

Résoudre l’exercice →