100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
YAML

Docker Compose Basics

Learn how Docker Compose defines and runs multi-container applications from a single YAML file, replacing long manual docker run commands.

Docker ContainersIntermediate11 min readJul 8, 2026
Analogies

Why Docker Compose

Real applications are rarely a single container — a typical web app needs a backend API, a database, and maybe a cache. Docker Compose lets you describe all of these services, their networks, and volumes in one YAML file, then start or stop the entire stack with a single command.

🏏

Cricket analogy: A full match-day setup isn't just the batting team but also umpires, ground staff, and broadcast crew, and Docker Compose is like the match director's single sheet that lines up every one of these units to start or wrap the whole day with one call.

Anatomy of a docker-compose.yml

A Compose file defines services (containers), and optionally volumes and networks that those services share. Each service maps closely to the flags you'd otherwise pass to docker run.

🏏

Cricket analogy: A Compose file's 'services' section listing db and web is like a scorecard listing every squad involved in the day, batting and bowling, and each entry mirrors exactly the instructions a captain would otherwise give each squad individually, like docker run flags.

yaml
services:
  api:
    build: ./api
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
      - DB_HOST=db
    depends_on:
      - db
    restart: unless-stopped

  db:
    image: postgres:16
    environment:
      - POSTGRES_PASSWORD=example
      - POSTGRES_DB=appdb
    volumes:
      - db-data:/var/lib/postgresql/data
    restart: unless-stopped

volumes:
  db-data:

Starting and Stopping the Stack

docker compose up builds (if needed) and starts every service defined in the file. docker compose down stops and removes the containers, and optionally the network and volumes.

🏏

Cricket analogy: docker compose up is like the toss followed by the umpire calling 'play' to start every unit of the match at once, while docker compose down is like stumps being called, packing up the ground, and optionally clearing the pitch and stands entirely.

bash
docker compose up -d              # build/start all services in the background
docker compose ps                 # list services and their status
docker compose logs -f api        # follow logs for just the 'api' service
docker compose down               # stop and remove containers and default network
docker compose down -v            # also remove named volumes (destroys data!)

docker compose down -v deletes the named volumes declared in the file, which permanently destroys any database data stored in them unless you have a backup.

Service Discovery and depends_on

Compose automatically creates a user-defined network for the project, so services can reach each other by their service name (e.g. db) just like with docker network create. depends_on controls startup order but does not wait for the dependency to be fully ready by default.

🏏

Cricket analogy: Compose creating a shared network so services reach each other by name like 'db' is like a stadium's internal radio channel where any staff member can just call out 'groundsman' by role and be heard, while depends_on merely ensures the groundsman arrives before play starts, not that the pitch is actually mowed yet.

yaml
services:
  api:
    build: ./api
    depends_on:
      db:
        condition: service_healthy
  db:
    image: postgres:16
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 3s
      retries: 5

Using condition: service_healthy alongside a healthcheck is the correct way to make one service wait until another is actually ready to accept connections, not just started.

Rebuilding and Scaling Services

When you change a Dockerfile or its build context, rebuild images before restarting. Compose can also run multiple replicas of a stateless service for simple local load testing.

🏏

Cricket analogy: Rebuilding images after changing a Dockerfile is like re-stringing a bat after altering its weighting before the next net session, and running multiple replicas locally is like setting up several bowling machines at once to simulate a full attack for practice.

bash
docker compose build              # rebuild images defined with 'build:'
docker compose up -d --build      # rebuild and restart in one step
docker compose up -d --scale api=3   # run 3 replicas of the 'api' service
  • docker-compose.yml defines services, networks, and volumes for a multi-container app in one file
  • docker compose up -d starts the whole stack; docker compose down stops and removes it
  • Services reach each other by service name via Compose's automatically created network
  • depends_on controls startup order only; combine with healthcheck + condition: service_healthy to wait for real readiness
  • docker compose down -v deletes named volumes — use with caution, it is destructive
  • docker compose logs -f <service> and docker compose ps are the primary debugging commands

Practice what you learned

Was this page helpful?

Topics covered

#YAML#DockerKubernetesStudyNotes#DevOps#DockerComposeBasics#Docker#Compose#Anatomy#Yml#StudyNotes#SkillVeris