Docker Networking Explained: Bridges, DNS and Why localhost Breaks
A mental model for Docker networks: how containers find each other, when to publish ports, and the difference between expose and ports. The mental model: networks are virtual switches Almost every Docker networking confusion dissolves with one picture: a user-defined bridge network is a virtual switch. Containers attached to it get a private IP and, crucially, a DNS name equal to their container…
Docker networking is a concept that can be understood by visualizing user-defined bridge networks as virtual switches. Containers attached to these networks receive private IP addresses and DNS names based on their container or service names, which are resolved by Docker's embedded DNS server. Containers on the same switch can communicate with each other by name on any port, while containers on different switches cannot see each other at all. The host can only reach containers through explicitly published ports.
There are two important concepts related to ports in Docker networking: ports and expose. The ports command binds a host port to a container's port, creating a doorway from the outside world to the container. Each host port can only be bound once. On the other hand, the expose command is used to document the ports that a container listens on, but does not affect the actual behavior.
When running containers, it is essential to follow the production rule: only the reverse proxy should publish ports (80/443), and all other applications and databases should remain network-internal. This eliminates port conflicts and accidental public databases.
Inside a container, localhost refers to the container's own loopback interface, not the host or sibling containers. There are two fixes to address this issue: use the network name (such as postgres, redis, or api) to reach a sibling service, or use host.docker.internal to reach something on the host machine. The latter is a Linux-specific solution that can be added using an extra_hosts mapping.
A common mistake occurs when an application inside a container binds to 127.0.0.1 (localhost) and becomes unreachable, even with published ports. This happens because the publish forwarding occurs at the container's external interface. To resolve this problem, containerized servers must listen on 0.0.0.0.
To troubleshoot connectivity issues, several commands can be used: docker network ls to see what virtual switches exist, docker network inspect to find out which containers are attached to a specific network, docker exec to run a command inside a container and check if DNS resolves, and docker exec with wget to test if you can actually reach the desired service.
Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.