Docker Networking Explained
Most "it can't connect" problems with Docker come from a few networking rules. Once you know them, they're easy to reason about.
User-defined bridge networks
docker network create appnet
docker run -d --name db --network appnet -e POSTGRES_PASSWORD=secret postgres:17
docker run -d --name api --network appnet -e DATABASE_URL=postgres://postgres:secret@db:5432/postgres my-api
Containers on the same user-defined network can reach each other by name (db), thanks to Docker's built-in DNS. Docker Compose creates such a network for each project automatically.
Publishing ports
docker run -p 8080:3000 my-api # host 8080 -> container 3000, on all interfaces
docker run -p 127.0.0.1:8080:3000 my-api # only reachable from this machine
Publishing is only needed for traffic from outside Docker. Container-to-container traffic on a shared network doesn't need -p.
The localhost trap
- Inside a container,
localhostmeans that container, not your machine. - To reach another container, use its service or container name.
- To reach a service on the host from a container, use
host.docker.internal(built in on Docker Desktop; on Linux add--add-host=host.docker.internal:host-gateway). - Your app must listen on
0.0.0.0, not127.0.0.1, or published ports won't reach it.
Other network modes
--network host- the container uses the host's network stack directly (Linux). Fast, but no isolation and no port mapping.--network none- no networking at all, for sandboxed jobs.- The default
bridgenetwork (when you don't specify one) has no DNS by name; prefer user-defined networks.
Debugging
docker network inspect appnet
docker exec -it api sh -c "wget -qO- http://db:5432 || nslookup db"
docker run --rm -it --network appnet nicolaka/netshoot # a toolbox of network tools
Was this article helpful?
Comments
No comments yet. Have a question or a tip? Be the first to share it.