Two settings connect the stack: the published port (host to web) and the database hostname (web to db). Each fails with its own symptom.
host network signup_default
curl localhost:8000 ──"8000:5000"──► web :5000
│ DB_HOST=db (service name)
▼
db :5432 not publishedRead the symptom
| Symptom | Cause | Fix in compose.yaml |
|---|---|---|
curl: (56) Recv failure: Connection reset by peer, container running | Mapping points at a container port nothing listens on | ports: ["8000:5000"] |
curl: (7) Failed to connect, container exited | The app crashed; read its logs first | Depends on the log |
could not translate host name "postgres" | Hostname is not a service on the network | DB_HOST: db |
Connection refused to db | db exists but is not running or not listening | Read docker compose logs db |
Port mappings
HOST:CONTAINER. The host side is what you curl. The container side must match the port the app listens on: app.py reads $PORT with default 5000, and the Dockerfile's EXPOSE 5000 documents it. EXPOSE publishes nothing by itself.
docker compose ps
docker compose port web 50000.0.0.0:8000Service hostnames
Compose puts every service on <project>_default and registers each service name in the network's DNS. Image names, container IDs and the host's localhost are not service names.
docker compose config --services
docker compose exec web getent hosts db172.18.0.2 dbgetent prints nothing and exits 2 for a name that does not resolve. db does not need ports: for web to reach it. Publishing Postgres only exposes it to the host.
Apply and verify
Edit compose.yaml, then docker compose up -d. Compose recreates only the services whose configuration changed. Verify from the outside in:
docker compose ps
curl localhost:8000/
curl -X POST "localhost:8000/signup?name=ana"