Docker Networking Explained: Bridges, DNS, and Published Ports
Docker Networking Explained: Bridges, DNS, and Published Ports
Docker networking is the part everyone glosses over until a container can't reach the database. Here's the model that matters, straight from how the Docker Engine actually implements it.
Table of Contents
- The default bridge — and its big limitation
- User-defined networks: where DNS lives
- The network drivers
- Publishing ports: the only door in
- Multi-homed containers and internal networks
- Subnets and IP management
- Debugging checklist
The default bridge — and its big limitation
When Docker starts, it creates a built-in bridge network. Every container launched without --network lands there, gets an IP, a gateway, DNS, and outbound access via NAT masquerading — so containers reach the internet out of the box.
The catch: on the default bridge, containers can only reach each other by IP address — no name resolution. Those IPs change on restart. This alone is why real apps go on user-defined networks.
User-defined networks: where DNS lives
docker network create -d bridge my-net
docker run -d --network=my-net --name api myapi
docker run -it --network=my-net busybox ping api # name resolution works
On a user-defined network, Docker's embedded DNS resolves container names and network aliases. This is also exactly what Compose does: it creates a per-project network so services resolve each other by service name.
The network drivers
- bridge — the default; private NAT'd network on one host.
- host — removes network isolation; the container shares the host's interfaces. Fast, no port mapping, but no isolation.
- none — fully isolated. Loopback only. Useful for batch jobs that shouldn't talk to anything.
- overlay — spans multiple Docker daemons (Swarm); encrypted VXLAN tunnels between hosts.
- ipvlan/macvlan — containers get real addresses on your physical LAN. Powerful for legacy network integration, tricky for routing.
Publishing ports: the only door in
All ports on a bridge-networked container are reachable from the host and sibling containers by default — but nothing reaches them from outside until you publish:
docker run -d -p 8080:80 nginx # host:8080 → container:80
docker run -d -p 127.0.0.1:8080:80 nginx # bind to localhost only
Binding to 127.0.0.1 is the habit to build: only publish to all interfaces (0.0.0.0) what genuinely needs to be public. An exposed database port you forgot about is a classic breach path.
Multi-homed containers and internal networks
A container can join multiple networks — like a host with multiple NICs. The production pattern: a frontend network for the proxy plus an --internal backend network that has no external route at all:
docker network create frontend
docker network create --internal backend
# proxy sees both worlds; db sees only backend
docker run -d --network backend --name db postgres:17
docker run -d --network backend --network frontend --name proxy nginx
docker network connect backend api-container
With --internal, the database can never be reached from the internet even if you mis-publish a port — isolation enforced by the network, not by discipline.
Subnets and IP management
Docker allocates subnets from built-in pools (172.17–31.0.0/x, 192.168.0.0/16). Override with --subnet, or reconfigure default-address-pools in /etc/docker/daemon.json — worth doing if your corporate VPN already uses 172.17.x and routes collide.
Debugging checklist
docker network ls
docker network inspect my-net # who's attached, what subnet
docker exec api ping -c1 db # name resolution + reachability
docker exec api getent hosts db # DNS answer specifically
docker port web # published port mappings
"Can't connect" is almost always one of: containers on different networks, hitting the container name on the default bridge (no DNS), or testing localhost from inside a container — which is the container itself, not your host.
Related Articles
- Dockerfile Best Practices: Building Small, Secure Images
- Running WordPress on Docker Compose in Production
Last Updated: October 2026 Author: CloudOpsGuide Team Difficulty: Intermediate Estimated Reading Time: 10 minutes