Docker compose for the Whole Stack

docker compose describes your entire system in one file. Postgres, Redis, the order service, the inventory service, the networking between them. One command spins it all up. One command tears it all down. This is how small teams ship to development and staging without spending a week on infra.

docker-compose.yml
yaml
services:
  db:
    image: postgres:15-alpine
    environment:
      POSTGRES_USER: bookstore
      POSTGRES_PASSWORD: bookstore
      POSTGRES_DB: bookstore
    volumes:
      - db_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U bookstore"]
      interval: 5s
      retries: 5

  redis:
    image: redis:7-alpine
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 5s
      retries: 5

  order-service:
    build: ./order-service
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_healthy
    environment:
      DATABASE_URL: postgres://bookstore:bookstore@db:5432/bookstore
      REDIS_URL: redis://redis:6379
      JWT_SECRET: replace_me
    ports:
      - "3000:3000"

  inventory-service:
    build: ./inventory-service
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_healthy
    environment:
      DATABASE_URL: postgres://bookstore:bookstore@db:5432/bookstore
      REDIS_URL: redis://redis:6379
    ports:
      - "4000:4000"

volumes:
  db_data:

Postgres, Redis, and the two services wired together with health checks.

Look at the depends_on blocks. The services do not just wait for the database container to start. They wait for its health check to pass. Postgres takes a couple of seconds to accept connections after the container starts, and without the health check your Node service crashes on startup with connection refused. condition: service_healthy fixes it in one line.

Inside the Compose network, services find each other by name. The order service talks to db and redis, not to an IP address. Docker handles the DNS for you. This is why DATABASE_URL uses @db:5432, not @localhost or an IP. One more moving part that Docker makes boring.

Quiz: Quiz

Loading practiceโ€ฆ