What is Docker Compose?
Docker Compose is a tool for running applications that consist of several containers at once. Most real apps are not a single program: you have a web server, a database, maybe a cache and a background worker. Compose lets you describe all of these in one file, usually named compose.yaml, and then start, stop, and connect them with a single command.
Without Compose, you start each container by hand with a long docker run command and wire them together yourself. With Compose, the file is the source of truth. Anyone on the team runs docker compose up and gets the same set of services, on the same network, with the same settings.
In plain words
Think of a single container as one appliance in a kitchen, like the oven. Docker Compose is the recipe card that says which appliances you need, how they connect, and in what order to turn them on. Instead of switching everything on by hand every morning, you hand over the card and the whole kitchen comes to life the same way every time.
How it works: a minimal example
You write a compose.yaml file that lists your services (each service becomes one or more containers), plus any networks and volumes they need. Here is a minimal example: a web app talking to a Postgres database.
services:
web:
build: .
ports:
- "8000:8000"
depends_on:
- db
db:
image: postgres:16
environment:
POSTGRES_PASSWORD: example
volumes:
- db-data:/var/lib/postgresql/data
volumes:
db-data:
Run docker compose up in that folder and Compose builds the web image, pulls the postgres:16 image, starts both, and puts them on a shared network. The web service reaches the database simply at the hostname db, because Compose handles the networking for you. The named volume db-data keeps the database files even after the containers stop. When you are done, docker compose down removes the containers cleanly.
When to use it, and when not
Use Compose when:
- You are developing locally and want one command to spin up the whole stack on a new machine.
- Your app has a few services that need to talk to each other, like an API, a database, and a queue.
- You run integration tests in CI and need real dependencies, not mocks, started fresh for each run.
Reach for something else when:
- You run in production at scale. Compose runs on a single host. For multiple servers, automatic restarts, and rolling updates, use an orchestrator like Kubernetes.
- You only have one container. A plain
docker runis simpler and Compose adds little.
Common pitfalls
- Treating Compose as a production platform. It is excellent for local dev and CI, but it does not give you load balancing or self-healing across machines.
- Hardcoding secrets in the file. Passwords and API keys belong in environment variables or a secrets manager, not committed in
compose.yaml. - Forgetting that named volumes persist. Data survives
docker compose down. To wipe it, you needdocker compose down -v, which is easy to run by accident. - Assuming
depends_onwaits for readiness. It controls start order, not whether a service is actually ready to accept connections. Add a healthcheck if the app needs the database to be up before it starts.
Related articles:
- SDK vs API: understanding the distinction - Two terms developers mix up, explained with clear examples.
- What is context engineering? - The skill of giving AI tools the right information at the right time.
- What is Vibe coding? - Building applications through AI, where prompting replaces writing code by hand.
Want to stay one step ahead?
Don't miss our best insights. No spam, just practical analyses, invitations to exclusive events, and podcast summaries delivered straight to your inbox.
