How containers talk to each other
A real app is usually at least two containers, an app and a database. But each container has its own isolated network world, its own localhost. If the app connects to localhost:5432, it finds nothing, because its localhost is itself, not the database container.
The answer is a user-defined network:
docker network create mynet docker run -d --name db --network mynet postgres:16 docker run -d --name app --network mynet -p 8080:8000 myapp:v1
Containers on the same network get two things:
- They can reach each other's ports directly, no
-pneeded between them - DNS by container name: the app connects to host
db, port5432, and Docker resolvesdbto the right container
So the app's database config is simply host=db port=5432. The only -p left is for you, the outside world, reaching the app.
Why user-defined? The default bridge trap
Containers started without --network land on Docker's built-in default network (called bridge), and it behaves differently in the one way that matters: no name-based DNS. On the default bridge, db does not resolve to anything, containers must find each other by IP address, and container IPs change on every restart. That is why every real setup creates its own network, name resolution is the feature you are opting into.
Useful commands and facts:
docker network ls # all networks on this machine docker network inspect mynet # which containers are attached, their IPs
- Containers can reach the internet by default (pulling packages works out of the box). The isolation is about what can reach them, and about container-to-container discovery
- One container can join several networks, which teams use to keep, say, a database reachable from the app but not from the public-facing proxy
Quiz
The app and db containers are both on network mynet. The app tries to reach Postgres at localhost:5432 and fails. Why?
Quiz
You start app and db containers without any --network flag, and the app cannot resolve the hostname db. What is the likely cause?
Problem
Your database container was started with --name db --network mynet. Your app container is on the same network. What hostname does the app put in its connection string to reach the database?