DevOps line
Docker Compose
One page draws a private hallway of rooms, and only one door opens onto the street.
Stops explain each step. The film plays the whole ride.
- Starting, or a call
- A note on its way
- Ready
- A call that failed
You open the plan
This one page names every room, the private hallway they share, and the cabinet outside. One word from you starts the whole floor.
Next stop: One private hallway
All stops
The everyday version
An office floor runs from one plan. The rooms share a private hallway, only the front desk opens onto the street, and the filing cabinet is fixed outside.
- Youis the You
Stands on the street and says start.
- The planis the Docker Compose
Names every room, the hallway, and the cabinet.
- The front deskis the api
The only room with a door onto the street.
- The records roomis the db
Must show a ready light before the front desk opens.
- The notice boardis the redis
Slow notes wait here until the back room has time.
- The back roomis the worker
Takes notes off the board and does the slow work out of sight.
- The filing cabinetis the pgdata
Stays put when the rooms are locked for the night.
- Wrong rooma connection refused error
The front desk looks for the records in its own room and finds nobody, because the records are down the hallway under their own name.
Interview questions
Say the short answer first. Go deeper only if they ask.
How do services find each other?
By service name: Compose puts every service on one project network with built-in DNS.
Compose creates a network called <project>_default, and each service registers its name as a host name. Use the container port, as in db:5432, never the published host port. Traffic between services ignores ports.
“Use localhost”, or hardcoding container IP addresses.
Does depends_on wait for the database to be ready?
Not by default. It only controls start order, and Compose waits until the container is running.
Add condition: service_healthy and a healthcheck such as pg_isready, so Compose waits for a passing check. Many teams also make the app retry its connection, because a dependency can restart later.
“depends_on guarantees the database accepts connections.”
What is the difference between ports and expose?
ports publishes a port on the host. expose only records a port for other containers and publishes nothing.
Containers on one network reach each other’s ports without either setting. Publishing binds all interfaces unless you add 127.0.0.1:, and db and redis usually need no ports at all.
“Services need ports to talk to each other.”
Where does the data live, and how do you reset it?
In a named volume. docker compose down keeps it, and docker compose down -v deletes it.
down removes containers and the project network, not named volumes. -v also removes the named volumes in the file and anonymous ones; external volumes are never removed. For Postgres 18 and newer mount at /var/lib/postgresql, for older versions /var/lib/postgresql/data.
“down deletes my database.”
What does localhost mean inside a container?
The container itself, not your laptop and not another service.
Each container has its own network namespace, so its loopback is private. Reach another service by its name, such as db. On Docker Desktop, host.docker.internal resolves to the host. A published port is how the host reaches a container.
“localhost is always my machine.”
How do you change the setup for another environment?
Keep compose.yaml as the base and layer compose.override.yaml on top. Compose reads both by default.
With -f you list files and they merge in order. Single-value fields such as command are replaced, while multi-value fields such as ports are concatenated. docker compose config prints the merged result.
“Keep a full copy of the file for each environment.”
How do you run several copies of a service?
Use docker compose up -d --scale worker=3, or set scale in the file.
The flag overrides scale in the file. A service with a container_name cannot go beyond one container, so leave naming to Compose.
“Set container_name on every service, then scale.”
Compose or Kubernetes?
Compose is the simple way to describe and run a stack on one server. Kubernetes manages containers across a cluster of nodes.
Docker says Compose works in development, testing, CI, staging and production, and its production guide starts with a single server. Kubernetes adds cluster features: it restarts failed containers, rolls out and rolls back changes, and scales horizontally.
“Compose is just Kubernetes on a laptop.”
Cheat-sheet
Commands you will actually type.
docker compose up -d --buildBuild images, then create and start every service in the background.
docker compose logs -f api workerFollow the logs of the services you name.
docker compose exec db psql -U appRun psql inside the running db container, as user app.
docker compose run --rm api pytestRun a one-off command in a new container, removed afterwards. It publishes no ports by default.
docker compose down -vRemove containers and the network. Plain down keeps named volumes, and -v deletes them too.
docker compose configPrint the merged, resolved configuration, including compose.override.yaml.
docker compose up -d --scale worker=3Run three worker containers. The flag overrides scale in the file.
depends_on: { db: { condition: service_healthy } }Wait for the db healthcheck to pass. Pair it with `test: ["CMD-SHELL", "pg_isready -U app"]` on db.
Sources
- Compose: networking
- Compose: startup order and depends_on
- Compose file: services (ports, expose, healthcheck, scale)
- Compose file: networks
- Compose file: volumes
- Compose: merge and override files
- Compose: project name
- Compose: application model (compose.yaml)
- Compose: getting started (down and down -v)
- Compose: overview
- Compose: in production
- CLI: docker compose up
- CLI: docker compose down
- CLI: docker compose run
- CLI: docker compose exec
- CLI: docker compose logs
- CLI: docker compose config
- Docker Engine: networking overview
- Docker Engine: host network driver
- Docker Engine: port publishing
- Dockerfile reference (HEALTHCHECK, EXPOSE)
- Docker Desktop: networking how-tos (host.docker.internal)
- Docker Hub: Postgres image
- PostgreSQL: pg_isready
- PostgreSQL: psql
- Celery: first steps (worker, broker)
- Redis: redis-cli (default port 6379, URI)
- Linux: network_namespaces(7)
- Kubernetes: overview