Docker
Intermediate 15 min read Docker

Docker Compose

Compose defines your whole application stack in one YAML file: services, networks, volumes and dependencies. It turns 'run these 5 docker commands' into docker compose up.

docker-compose.ymlservicesdepends_onscaleprofile
Introduction

What is this?

Docker Compose is a tool for defining and running multi-container applications. A docker-compose.yml declares every service, its image/build, ports, env, volumes and networks. Compose creates the networks and volumes automatically and wires everything together.

Motivation

Why do you need it?

  • One file replaces a fragile chain of docker run commands.
  • Config is version-controlled and reviewable like code.
  • Automatic network creation gives every service DNS by its service name.
  • Repeatable: the same file produces the same stack on any machine.
Think about it

Mental model

Imagine

An assembly manual

Think of

docker-compose.yml

The manual lists every part (services) and how they fit (networks/volumes). Anyone who follows it builds the same product — every environment gets the same stack.

Mechanics

How it works

  • Compose reads the YAML and computes the full resource graph (services, networks, volumes).
  • docker compose up creates resources in dependency order (depends_on).
  • Services on the same project share a default network and resolve each other by service name.
  • Volumes declared at the top level are created once and reused across service restarts.
  • docker compose down removes the project's containers and, with -v, its volumes.

A Compose stack's resource graph.

docker-compose.yml
web service
api service
db service
app-network
Reference

Key commands

docker compose up -d

Start the stack detached.

docker compose down -v

Stop and remove containers AND volumes.

docker compose ps

Show service status.

docker compose logs -f api

Stream logs for one service.

docker compose up --build -d

Rebuild images then start.

Hands-on

Examples

A three-service stack

A three-service stack
services:
web:
image: nginx
ports: ["8080:80"]
depends_on: [api]
api:
build: ./api
environment:
DATABASE_URL: postgres://user:pass@db:5432/app
db:
image: postgres:16
environment:
POSTGRES_PASSWORD: pass
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
pgdata:

web, api and db join a default network. The API connects to the DB via hostname 'db'. The pgdata named volume persists the database across down/up cycles.

Real world

In production

  • Single-host deployments and local dev get a reproducible stack from one file.
  • Overrides (docker-compose.override.yml) differ per environment while the base stays clean.
  • CI uses compose to spin up ephemeral dependencies (Redis, Postgres) for tests.
  • Readiness is handled with healthcheck + condition in depends_on for ordered startup.
Guidelines

Best practices

  • Use named volumes for databases so data survives down/up.
  • Set restart: unless-stopped on long-running services.
  • Keep secrets out of the file — use env_file or $VARIABLE substitution.
  • Pin image versions in the file.
Watch out

Common mistakes

  • Relying on default depends_on (wait-for-started, not wait-for-ready) for ordering.
  • Putting credentials directly in YAML and committing them.
  • Using docker compose down -v blindly in production (destroys volumes).
  • Not using a version-pinned image, so behavior drifts.
Root cause analysis

Common issues

Error
Service 'api' depends on 'db' which is unhealthy
Root cause

depends_on with condition: service_healthy but db has no healthcheck.

Fix

Add a healthcheck to the db service (e.g. pg_isready).

Error
Cannot connect to the Docker daemon ... Is 'docker compose' project name invalid?
Root cause

Project name contains characters Docker rejects (e.g. uppercase or slashes).

Fix

Set an explicit project name: docker compose -p myapp up -d.

Error
Network conflict: network name is already in use
Root cause

Two compose projects generated the same network name.

Fix

Use distinct -p project names so networks are namespaced.

When things break

Debugging tips

  • docker compose config to see the fully rendered, valid config.
  • docker compose ps to see health and exit codes.
  • docker compose logs --tail=50 to find the failing service's error.
  • docker compose up --no-start then docker compose start for manual stepping.
Interviews

Interview checkpoint

Practice

Hands-on lab

Orchestrate a Full Stack with Compose
40 min · intermediate
In progress
Objectives
  • Define a multi-service compose stack
  • Wire services over a shared network
  • Persist the database with a named volume
  • Tear down safely without data loss

Orchestrate a Full Stack with Compose

40 min · intermediate

0/6 steps
0%
sandbox · Linux sandbox
$
Try these commands
Test yourself

Quick quiz

0/3
1

Which command stops services and removes their named volumes?

2

By default, services in a Compose project communicate using...

3

docker compose up -d waits for databases to be ready by default.

Quick reference

Cheat sheet

Compose
docker compose up -dStart stack detached
docker compose downStop + remove containers
docker compose down -vAlso remove volumes
docker compose psService status
docker compose logs -fStream logs
docker compose configValidate + render config
Go deeper

Official documentation