Docker Compose
Docker Compose
Section titled “Docker Compose”Docker Compose defines and runs multi-container applications using a single YAML file. Instead of running several docker run commands and manually linking containers, Compose brings up the entire stack with one command.
Basic docker-compose.yml
Section titled “Basic docker-compose.yml”version: '3.8'
services: api: build: . ports: - "3000:3000" environment: - DATABASE_URL=postgresql://postgres:password@db:5432/mydb depends_on: - db
db: image: postgres:16 environment: POSTGRES_USER: postgres POSTGRES_PASSWORD: password POSTGRES_DB: mydb volumes: - postgres-data:/var/lib/postgresql/data
volumes: postgres-data:Core Commands
Section titled “Core Commands”# Start all services (build if needed)docker compose up
# Start in detached mode (background)docker compose up -d
# Build images without startingdocker compose build
# Stop and remove containersdocker compose down
# Stop and remove containers + volumesdocker compose down -v
# View logsdocker compose logsdocker compose logs -f api # follow logs for one service
# Restart a servicedocker compose restart api
# Run a one-off command in a servicedocker compose run api npm run migrate
# Execute in a running containerdocker compose exec api shFull Stack Example: Node.js + Postgres + Redis
Section titled “Full Stack Example: Node.js + Postgres + Redis”version: '3.8'
services: api: build: context: . dockerfile: Dockerfile ports: - "3000:3000" env_file: - .env depends_on: db: condition: service_healthy redis: condition: service_started volumes: - .:/app # mount source code for hot reload - /app/node_modules # keep container's node_modules
db: image: postgres:16-alpine environment: POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_DB: ${POSTGRES_DB} volumes: - postgres-data:/var/lib/postgresql/data - ./init.sql:/docker-entrypoint-initdb.d/init.sql healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"] interval: 10s timeout: 5s retries: 5
redis: image: redis:7-alpine command: redis-server --requirepass ${REDIS_PASSWORD}
nginx: image: nginx:alpine ports: - "80:80" volumes: - ./nginx.conf:/etc/nginx/conf.d/default.conf depends_on: - api
volumes: postgres-data:Multiple Compose Files
Section titled “Multiple Compose Files”Override settings for different environments:
# Developmentdocker compose -f docker-compose.yml -f docker-compose.dev.yml up
# Productiondocker compose -f docker-compose.yml -f docker-compose.prod.yml updocker-compose.dev.yml:
services: api: volumes: - .:/app command: npm run dev # hot reload environment: - NODE_ENV=developmentdocker-compose.prod.yml:
services: api: restart: unless-stopped environment: - NODE_ENV=productionHealth Checks
Section titled “Health Checks”services: api: healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3000/health"] interval: 30s timeout: 10s retries: 3 start_period: 40sScaling Services
Section titled “Scaling Services”# Run 3 instances of the api servicedocker compose up -d --scale api=3Requires a load balancer (nginx or Traefik) in front — multiple containers can’t bind the same host port.
Viewing Resources
Section titled “Viewing Resources”# List containersdocker compose ps
# Resource usagedocker compose top
# List images useddocker compose images