Imagine you have a complex microservice. For local development, you need it connected to a message queue, a telemetry collector, and a database. But for your E2E testing, you need a slightly modified version (different env vars, an extra mock dependency, maybe a different port).
Most engineers solve this by maintaining two massive, almost-identical YAML files. It is a nightmare to sync changes.
Or they simply do this:
$ docker compose -f compose.yml -f e2e-compose.yml up --build -d
I do NOT like neither of them. Instead use YAML Anchors (&), Merge Keys (<<:), and Compose Profiles to create a single, DRY (Don't Repeat Yourself) configuration file.
# ------------------------------------------------------------
# 1. REUSABLE BUILDING BLOCKS (Anchors)
# ------------------------------------------------------------
x-backend-depends-on: &backend-depends-on
message-queue:
condition: service_healthy
telemetry-collector:
condition: service_started
x-backend-config: &backend-config
build: .
user: "1000:1000"
ports:
- "3000:$PORT"
env_file:
- .env
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:${PORT:-3000}/health"]
interval: 5s
timeout: 5s
retries: 12
start_period: 10s
depends_on: *app-depends-on
# ------------------------------------------------------------
# 2. SERVICES
# ------------------------------------------------------------
services:
# --- Production / Dev Service ---
backend:
<<: *backend-config
profiles: ["dev"]
# --- E2E Test Variant ---
backend-e2e:
<<: *app-config
profiles: ["e2e"] # Only starts when explicitly called
environment: # Override specific ENV vars for testing
RETRY_DELAY_MS: "100"
TIMEOUT_MS: "200"
depends_on:
<<: *app-depends-on # Inherit all base dependencies
e2e-fixture: # ADD an extra dependency for testing
condition: service_healthy
# ...
So now how this changes your workflow:
- Local:
docker compose --profile dev upstarts only backend + services in default/dev profile. - E2E testing:
docker compose --profile e2e upautomatically swaps in backend-e2e, overrides timeouts/retries.
Top comments (0)