CodeOath
← All posts
Docker65 min total · 19 parts

Docker Fundamentals: Images, Containers, and Writing a Good Dockerfile

Contents — Part 13 of 19: Docker Compose: Running More Than One Container Together
Part 13 of 19 · ~1 min

Docker Compose: Running More Than One Container Together

Almost nothing real is a single container — you've got an app, a database, maybe Redis. docker-compose.yml declares all of them, plus the network and volumes tying them together, in one file:

services:
  web:
    build: .
    ports: ["3000:3000"]
    environment:
      - DATABASE_URL=postgres://db:5432/app
    depends_on:
      db:
        condition: service_healthy
  db:
    image: postgres:16
    environment:
      - POSTGRES_PASSWORD=devpassword
    volumes: ["pgdata:/var/lib/postgresql/data"]
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 3s
      retries: 5
volumes:
  pgdata:

docker compose up builds and starts everything declared, wired together on a shared user-defined network where web can reach db by service name alone — this is the "automatic name resolution" mentioned in the networking section, provided for free by Compose. docker compose down tears everything back down; add -v to also remove the declared volumes (data loss, deliberately opt-in).

depends_on controls start order, not readiness — by default, Compose starts db before web but doesn't wait for Postgres to actually be ready to accept connections, just for its container process to have started. condition: service_healthy (paired with a healthcheck, above) is what actually makes Compose wait for the dependency to be ready, not merely started — a very common source of "works when I restart it, fails on first up" bugs is relying on plain depends_on for a database that takes a few seconds to initialize before accepting connections.