AcademyContainment Breach: The Architect's ShipZone 6: Fleet Operations (Compose)

Lesson 2: The Full Stack (Real-World Compose)

Let's build a production-ready Docker Compose setup for a full-stack application — the kind you'd actually use at a company.

A Real-World Stack

version: "3.8"

services:
  # Frontend - React/Next.js
  frontend:
    build:
      context: ./frontend
      dockerfile: Dockerfile
    ports:
      - "3000:3000"
    environment:
      - API_URL=http://api:4000
    depends_on:
      - api

  # Backend API - Node.js/Express
  api:
    build:
      context: ./api
      dockerfile: Dockerfile
    ports:
      - "4000:4000"
    environment:
      - DATABASE_URL=postgres://postgres:secret@db:5432/myapp
      - REDIS_URL=redis://cache:6379
    depends_on:
      db:
        condition: service_healthy
      cache:
        condition: service_started

  # Database - PostgreSQL
  db:
    image: postgres:15-alpine
    volumes:
      - postgres-data:/var/lib/postgresql/data
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: secret
      POSTGRES_DB: myapp
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 5s
      retries: 5

  # Cache - Redis
  cache:
    image: redis:alpine
    volumes:
      - redis-data:/data

  # Reverse Proxy - Nginx
  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
    depends_on:
      - frontend
      - api

volumes:
  postgres-data:
  redis-data:

Advanced Compose Features

Health Checks

Wait for a service to be truly ready, not just running:

healthcheck:
  test: ["CMD-SHELL", "pg_isready -U postgres"]
  interval: 5s
  timeout: 5s
  retries: 5

Environment Files

Keep secrets out of your compose file:

services:
  api:
    env_file:
      - .env

Profiles (Dev vs. Production)

services:
  debug-tools:
    image: busybox
    profiles:
      - debug
docker compose up                  # Doesn't start debug-tools
docker compose --profile debug up  # Includes debug-tools

Override Files

# docker-compose.yml         → Base configuration
# docker-compose.override.yml → Dev overrides (auto-loaded)
# docker-compose.prod.yml    → Production config

docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d

Debugging Compose Applications

# View all logs
docker compose logs -f

# Logs for one service
docker compose logs -f api

# Shell into a service
docker compose exec api sh

# Rebuild after code changes
docker compose up -d --build

# View resource usage
docker compose top
booting...

Mission Objective

Manage a full-stack application:

  1. Monitor: Run docker compose logs --tail 10 to see recent output.
  2. Connect to DB: Run docker compose exec db psql -U postgres to access PostgreSQL.
  3. Tear down: Run docker compose down to cleanly stop everything.

Mission Control

View logs from all services

Expected Command

docker compose logs --tail 10

Connect to the database service

Tear down the entire stack