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 composecommand 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.

