Optimizing Docker Compose: Using YAML Anchors and Merge Keys to Clean Up Redundant Code

Docker tutorial - IT technology blog
Docker tutorial - IT technology blog

The “Copy-Paste” Nightmare in Docker Compose

Opening a 500-line docker-compose.yml file only to find that 80% is repetitive code? Any DevOps engineer has likely felt this frustration. As projects scale from a few containers to complex microservices systems, repeating environment, networks, or logging becomes a real burden.

Imagine having 10 services sharing the same log configuration. Every time you want to change the log size from 10MB to 50MB, you have to edit 10 different places. Miss just one, and the system becomes inconsistent. This is where YAML Anchors (&) and Merge Keys (<<:) shine. They allow for smart code reuse directly within the YAML file without needing third-party tools.

Quick Start: Clean Up Your Compose File in 5 Minutes

Instead of writing things over and over, we define a common “template.” Let’s see how I optimize the configuration file below:

version: "3.9"

# 1. Create a template using Extension Fields (starting with x-)
x-common-setup: &common-config
  restart: always
  networks:
    - backend-network
  logging:
    driver: "json-file"
    options:
      max-size: "10m"
      max-file: "3"

services:
  web-api:
    # 2. Use Merge Key to pull in the configuration
    <<: *common-config
    image: my-api:latest
    ports:
      - "8080:8080"

  worker-process:
    <<: *common-config
    image: my-worker:latest
    environment:
      - NODE_ENV=production

networks:
  backend-network:
    driver: bridge

The result is surprising. The configuration file is now extremely clean. If you need to change the max-size for logs, you only need to edit a single line in x-common-setup.

Decoding the Trio: Anchors, Aliases, and Merge Keys

1. Anchor (&) – The Marker

The & symbol is like naming a variable. You place it right before the data block you want to reuse (e.g., &my-config). Docker remembers the entire content of this block for later use.

2. Alias (*) – Retrieving Data

The * symbol acts as a callback to the saved variable. When you write *my-config, YAML understands that you want to copy the entire content from the declared Anchor into that position.

3. Merge Key (<<:) – Merging Configurations

This is the most valuable feature. If you only use an Alias (*), you replace the entire key’s value. But with <<:, you can merge attributes from an Anchor into the current service. You can still freely add specific configurations or override old values if needed.

services:
  auth-service:
    <<: *common-config # Get common configuration
    environment:
      - SERVICE_NAME=auth # Add specific environment variable
    restart: on-failure # Override the 'always' attribute

Advanced Techniques for Large Microservices Projects

In practice, I often split Anchors based on their purpose instead of grouping them in one place. Using Extension Fields (keys starting with x-) is a great tip. Docker Compose ignores these keys during execution, making them ideal template holders.

x-env-base: &env-base
  environment:
    - DB_HOST=postgres
    - REDIS_URL=redis://cache:6379

x-deploy-limits: &deploy-limits
  deploy:
    resources:
      limits:
        cpus: '0.50'
        memory: 512M

services:
  payment-service:
    <<: [*env-base, *deploy-limits] # Merge multiple Anchors at once
    image: payment:v1

When working with complex YAML files, debugging can be a headache. To check if the merge result is correct, I often use online data formatting tools. You can try pasting your configuration into the JSON Formatter at Toolcraft to spot errors faster. This helps me immediately identify incorrectly overridden keys without having to run the container.

3 Crucial Notes to Avoid Errors

  • Order is extremely important: You must define the Anchor (&) above before calling the Alias (*) below. If placed in reverse, Docker will report a reference error.
  • The Array Trap: Merge Keys work perfectly with key-value pairs (maps). However, with lists (arrays), they overwrite the entire list rather than appending to it. If the Anchor has 3 environment variables and the service also defines environment, the old list will disappear completely.
  • Prioritize Docker Compose V2: Use the docker compose command instead of the old version to take advantage of the best YAML processing capabilities.

Final Thoughts from Real-World Experience

Don’t over-rely on Anchors for overly simple things. If an attribute only appears twice, creating an Anchor might make the file harder to read. I usually only apply this technique to logging configurations, database environment variables, or resource limits (CPU/RAM). A professional docker-compose.yml file is one that clearly shows the system structure, not a maze of repetitive code.

Share: