Docker Compose — YAML Extensions

1 minute read

YAML extensions (the x- prefix) let you define reusable configuration blocks in your compose file — keeping it DRY (Don’t Repeat Yourself).

The Problem: Repetition

services:
  api:
    image: node:20-alpine
    restart: unless-stopped
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"

  worker:
    image: node:20-alpine
    restart: unless-stopped
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"

  scheduler:
    image: node:20-alpine
    restart: unless-stopped
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"

Three services, identical restart and logging config. Let’s DRY it up.

The Solution: x- Extensions

x-common: &common
  restart: unless-stopped
  logging:
    driver: json-file
    options:
      max-size: "10m"
      max-file: "3"

services:
  api:
    <<: *common
    image: node:20-alpine

  worker:
    <<: *common
    image: node:20-alpine
    command: node worker.js

  scheduler:
    <<: *common
    image: node:20-alpine
    command: node scheduler.js

How It Works

  1. x-common: — Any top-level key starting with x- is an extension (ignored by Compose)
  2. &common — YAML anchor (names the block)
  3. <<: *common — YAML merge key (inserts the block)

Multiple Extensions

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

x-healthcheck: &healthcheck
  healthcheck:
    interval: 10s
    timeout: 5s
    retries: 3

services:
  api:
    <<: [*logging, *healthcheck]
    image: myapi:latest
    healthcheck:
      test: ["CMD-SHELL", "curl -f http://localhost:3000/health"]

Verify Resolution

docker compose config

This outputs the fully resolved file with all extensions merged.

Rules

Rule Detail
Prefix Must start with x-
Scope Top-level only
Ignored by Compose Yes (pure YAML feature)
Override Local keys override merged values

Summary

Feature Syntax
Define extension x-name: &anchor
Use extension <<: *anchor
Multiple <<: [*a, *b]
Override Local key wins over merged
Verify docker compose config

Quick Reference

Item Detail
x-name: Extension block (ignored by Compose)
&anchor YAML anchor (name the block)
«: *anchor Merge the block into a service
Override Local keys win over merged values
Verify docker compose config