Compose commands take service names, not container names. They find the project from the compose.yaml in the current directory (or a parent).
| Command | Does |
|---|---|
docker compose up -d | create what is missing, recreate what changed, start everything, return |
docker compose ps [-a] | this project's containers (-a includes exited ones) |
docker compose logs [-f] [SERVICE] | logs of every service, or one; -f follows |
docker compose exec SERVICE CMD | run a command in the service's running container |
docker compose run --rm SERVICE CMD | run a command in a new one-off container |
docker compose config | print the resolved, validated file |
docker compose ls | every Compose project on this host |
The project name
The project name prefixes every object. Compose takes the first of:
1. docker compose -p NAME ...
2. COMPOSE_PROJECT_NAME in the shell environment
3. top-level name: in compose.yaml
4. the directory namename: workshop
services:
web:
build: .
...Start
docker compose up -d[+] Running 4/4
✔ Network workshop_default Created 0.1s
✔ Volume "workshop_db-data" Created 0.0s
✔ Container workshop-db-1 Healthy 4.3s
✔ Container workshop-web-1 Started 0.3sOn the first run Compose also pulls postgres:16 and builds workshop-web; that output comes before the block above.
ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
workshop-db-1 postgres:16 "docker-entrypoint.s…" db 6 seconds ago Up 6 seconds (healthy) 5432/tcp
workshop-web-1 workshop-web "python app.py" web 2 seconds ago Up 2 seconds 0.0.0.0:8000->5000/tcp5432/tcp without an arrow means the port is open on the project network only. 0.0.0.0:8000->5000/tcp is published on the host.
logs
Each line is prefixed with the service and replica number:
web-1 | * Serving Flask app 'app'
web-1 | * Running on http://127.0.0.1:5000
db-1 | 2026-10-11 20:49:15.625 UTC [1] LOG: database system is ready to accept connectionsdocker compose logs web limits output to one service. -f keeps printing new lines until Ctrl+C. When a service is missing from ps, docker compose ps -a and docker compose logs SERVICE tell you why it exited.
exec
exec allocates a terminal by default, so interactive programs work:
docker compose exec db psql -U postgres
docker compose exec db psql -U postgres -c 'SELECT * FROM signups'
docker compose exec web envAdd -T in scripts and CI, where there is no terminal.
config
docker compose config shows what Compose will actually use: relative paths made absolute, short forms expanded, variables substituted, defaults filled in.
web:
build:
context: /home/learner/signup
dockerfile: DockerfileRun it after every edit. If it prints an error, up would fail with the same error.