level 08 / docker-compose
Docker Compose for Test Stacks
Orchestrate multi-service test environments with Docker Compose — app, database, and test runner together.
Test Stack Architecture
Basic docker-compose.yml
# docker-compose.yml
version: '3.9'
services:
app:
image: my-app:latest
build: .
ports:
- "3000:3000"
environment:
DATABASE_URL: postgres://user:pass@db:5432/testdb
REDIS_URL: redis://redis:6379
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 5s
timeout: 3s
retries: 10
db:
image: postgres:16-alpine
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: pass
POSTGRES_DB: testdb
healthcheck:
test: ["CMD-SHELL", "pg_isready -U user -d testdb"]
interval: 3s
timeout: 3s
retries: 15
redis:
image: redis:7-alpine
pw-tests:
image: mcr.microsoft.com/playwright:v1.45.0-jammy
working_dir: /app
volumes:
- .:/app
- playwright-report:/app/playwright-report
environment:
BASE_URL: http://app:3000
DATABASE_URL: postgres://user:pass@db:5432/testdb
CI: "true"
command: npx playwright test
depends_on:
app:
condition: service_healthy
volumes:
playwright-report:
Running the Stack
# Start all services and run tests
docker compose up --exit-code-from pw-tests
# Exit code matches the test runner exit code:
# 0 = all tests passed
# 1 = test failures
# Use for CI pass/fail
# Teardown (remove containers + networks)
docker compose down
# With volume cleanup
docker compose down -v
Override File for CI vs Local
# docker-compose.override.yml (local dev — not committed or committed separately)
services:
pw-tests:
command: npx playwright test --headed
environment:
PWDEBUG: "1"
# docker-compose.ci.yml (CI-specific overrides)
services:
pw-tests:
command: npx playwright test --reporter=blob,junit
# CI usage
docker compose -f docker-compose.yml -f docker-compose.ci.yml up --exit-code-from pw-tests
Healthchecks — Critical for Test Reliability
Without healthchecks, the test container starts before the app is ready:
app:
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 5s
retries: 10
pw-tests:
depends_on:
app:
condition: service_healthy # wait until app healthcheck passes
Database Seeding
db-seed:
image: postgres:16-alpine
environment:
PGPASSWORD: pass
command: >
sh -c "
until pg_isready -h db -U user; do sleep 1; done
psql -h db -U user -d testdb -f /seeds/seed.sql
"
volumes:
- ./seeds:/seeds
depends_on:
db:
condition: service_healthy
Useful Commands
# Watch test logs
docker compose logs -f pw-tests
# Run specific test file
docker compose run --rm pw-tests npx playwright test e2e/auth.spec.ts
# Open interactive shell in test container
docker compose run --rm pw-tests bash
# Scale workers
docker compose up --scale pw-tests=4 # 4 test containers (shard-like)