Retour au cours

infra / docker-compose

YAML avancé : ancres, alias et fusion (merge keys)

Leçon 151 exercice

Explication

Ce que vous allez apprendre

  • Déclarer un bloc de configuration réutilisable avec une ancre YAML (&nom)
  • Réutiliser ce bloc ailleurs dans le fichier avec un alias (*nom)
  • Fusionner un bloc ancré dans un service tout en y ajoutant des clés propres (<<:)
  • Utiliser la convention x- pour ranger ces blocs sans qu'ils soient interprétés comme des services
  • Repérer que ce mécanisme appartient au langage YAML lui-même, pas seulement à Compose

Dans quel contexte ?

Sur le projet boutique-api, les services api et worker partagent exactement le même healthcheck et la même politique de logs, copiés-collés service par service. Le jour où l'équipe doit changer l'intervalle du healthcheck de 10 à 15 secondes, elle oublie de le faire sur worker, qui continue de tourner avec l'ancienne valeur pendant plusieurs semaines sans que personne ne s'en aperçoive. Les ancres YAML éliminent ce risque en centralisant la définition.

Le problème : du copier-coller dans le YAML

D'abord, imagine plusieurs services qui partagent presque le même healthcheck ou la même politique de logs. Sans solution particulière, on finit par copier-coller cette configuration service après service dans le fichier.

Le risque de cette duplication

Le jour où il faut changer une seule valeur, il faut la changer partout où elle a été copiée. Il est alors facile d'en oublier une, exactement comme pour la duplication de code dans un vrai programme.

Une précision avant de continuer

Il faut savoir que ce mécanisme n'appartient pas à Compose : c'est une fonctionnalité du langage YAML lui-même, utilisable dans n'importe quel fichier YAML, pas seulement docker-compose.yml.

Première brique : l'ancre

Une ancre, écrite &nom, marque un bloc de configuration comme réutilisable. C'est un peu comme donner un nom à une variable, mais pour un bloc entier de configuration.

Deuxième brique : l'alias

Une fois une ancre définie, un alias, écrit *nom, permet de réutiliser ce bloc ailleurs dans le fichier, tel quel, sans jamais le retaper.

Aller plus loin : la fusion avec <<:

Il reste un besoin : réutiliser un bloc ET lui ajouter des clés supplémentaires. C'est le rôle de la clé de fusion <<:, qui injecte le contenu d'un bloc ancré dans un autre mapping, avant d'ajouter ou de surcharger certaines valeurs localement.

Où ranger ces blocs réutilisables

Maintenant que tu sais créer des ancres, une question d'organisation se pose : où les placer sans polluer la liste des vrais services ? Compose répond en ignorant volontairement toute clé de premier niveau commençant par x-, une convention prévue justement pour stocker ces blocs.

SymboleNomRôle
&nomAncreMarque un bloc comme réutilisable
*nomAliasRéférence le bloc ancré tel quel
<<:Clé de fusionInjecte le bloc ancré, puis autorise des ajouts locaux
x-nomExtensionClé racine ignorée par Compose, faite pour stocker des ancres

Les pièges à connaître

Une clé définie localement après un <<: écrase la valeur héritée de l'ancre, ce qui est utile pour personnaliser un bloc partagé mais peut surprendre si on ne s'y attend pas. Attention aussi à ne pas abuser des ancres au point de rendre le fichier illisible : garde le réflexe de toujours vérifier le résultat final avec docker compose config.

Bonne pratique

Regroupe toutes tes ancres réutilisables sous des clés x- en haut du fichier (x-healthcheck-default, x-logging-default) plutôt que de les disperser. N'importe quel nouveau membre de l'équipe comprend alors immédiatement où chercher la configuration partagée.

La leçon suivante change complètement de sujet : au lieu d'alléger le fichier YAML, elle installe un reverse proxy capable de router automatiquement le trafic vers tes services, sans jamais éditer sa configuration à la main.

Commandes & code

YAML avancé : ancres, alias et fusion (merge keys)

Les ancres YAML évitent de dupliquer une configuration identique entre plusieurs services d'un même fichier Compose.

yaml
# Ancre (&nom) définit un bloc réutilisable, alias (*nom) le référence tel quel
x-healthcheck-default: &default-healthcheck
  interval: 10s
  timeout: 3s
  retries: 5
  start_period: 15s

x-logging-default: &default-logging
  driver: json-file
  options:
    max-size: "10m"
    max-file: "3"

services:
  api:
    build: ./api
    healthcheck:
      <<: *default-healthcheck                      # fusionne le bloc ancré ici
      test: ["CMD", "wget", "-qO-", "http://localhost:3000/health"]
    logging: *default-logging

  worker:
    build: ./worker
    healthcheck:
      <<: *default-healthcheck
      test: ["CMD", "node", "healthcheck.js"]
    logging: *default-logging
yaml
# "x-" est un préfixe réservé par Compose : ces clés sont ignorées à l'exécution,
# elles servent UNIQUEMENT de zone de définition pour ancres/alias réutilisables.

x-common-env: &common-env
  TZ: Europe/Paris
  LOG_FORMAT: json

services:
  api:
    build: ./api
    environment:
      <<: *common-env
      SERVICE_NAME: api        # clé supplémentaire propre à ce service

  worker:
    build: ./worker
    environment:
      <<: *common-env
      SERVICE_NAME: worker
yaml
# Fusion de PLUSIEURS ancres avec la syntaxe de liste de merge keys
x-base: &base
  restart: unless-stopped

x-resources: &resources
  deploy:
    resources:
      limits:
        memory: 256M

services:
  api:
    build: ./api
    <<: [*base, *resources]     # fusionne les deux blocs au niveau racine du service
bash
# Toujours valider le résultat final : les ancres/alias sont résolus AVANT interprétation
docker compose config

Résumé

  • &nom déclare une ancre, *nom la référence, <<: fusionne un mapping ancré dans un autre.
  • Le préfixe x- marque des clés d'extension ignorées par Compose, idéales pour stocker des ancres.
  • Une clé locale après <<: écrase la valeur héritée de l'ancre (comme un override).
  • docker compose config affiche toujours le YAML une fois les ancres/alias résolus.

Exercices pratiques

1 disponible
1

Mission : deux services, un seul healthcheck qui diverge

Objectif : Prédire le résultat d'une fusion d'ancre YAML avec surcharge locale, puis factoriser une configuration dupliquée.

Contexte

Sur boutique-api, une ancre &default-healthcheck définit interval: 10s. Le service worker utilise <<: *default-healthcheck puis redéfinit localement interval: 30s. Par ailleurs, api et worker dupliquent exactement la même configuration logging, copiée-collée service par service.

Prédis le résultat de la fusion, puis factorise la configuration dupliquée.

Résoudre l’exercice →