Backend / Docker / 07_networks_bridge_vs_nat_vs_host.md

Docker network modes

Updated 5 interview angles 4 min read source
On this page8
  1. Bridge: the default, and why
  2. Host: no namespace, no mapping
  3. None, and custom
  4. Overlay: across hosts
  5. Publishing, precisely
  6. Talking to the host
  7. Related
  8. Interview angle

Docker network modes

Mode Isolation Use for
bridge own namespace the default
host none latency, packet capture
none total untrusted batch work
overlay own, multi-host Swarm across nodes

Bridge: the default, and why

Each container gets its own network namespace and a virtual interface on a Linux bridge. Traffic to the outside is NAT’d; traffic in only arrives on ports you publish.

bash
docker run -p 8080:80 nginx
#            │    └── container port
#            └─────── host port

Isolation is the point: two containers can both listen on 80 without conflicting, because each has its own stack. The cost is a NAT hop, which matters only at high packet rates.

The default bridge has no DNS

This is the distinction interviewers probe:

bash
docker run --name db postgres
# Fails: the default bridge has no DNS.
docker run --rm alpine ping db

docker network create app
docker run --network app --name db postgres
docker run --network app --rm alpine ping db   # works

A user-defined bridge runs an embedded DNS server, so containers resolve each other by name and by network alias. The legacy default bridge does not — it only had --link, which is deprecated.

That is exactly why Compose creates a network per project and why service names just work there. Nothing magic; it is a user-defined bridge.

Host: no namespace, no mapping

bash
# Binds the host's :80 directly.
docker run --network host nginx

The container shares the host’s network stack. -p is meaningless and ignored. You get the host’s interfaces, its ports and its packet view.

Justified when:

  • Latency or throughput matters enough that the NAT hop shows up. This is a real effect at high connection rates, not a rounding error.
  • You need the host’s exact stack — packet capture, network monitoring, a service discovering peers by the host’s real IP.
  • A protocol assigns many dynamic ports (some RTP/SIP setups), where publishing a range is impractical.

The costs are the mirror image: no port-conflict protection, no isolation, and Linux-only semantics. On Docker Desktop the “host” is the Linux VM, not your laptop, which surprises people.

None, and custom

--network none gives a loopback interface and nothing else. The honest sandbox for running something untrusted that has no business making network calls.

--network container:<name> shares another container’s namespace — the same mechanism that puts a Kubernetes sidecar on the same localhost as its app.

Overlay: across hosts

An overlay network spans machines using VXLAN, so a container on host A reaches one on host B by name. It is the Swarm answer to multi-host networking; on Kubernetes the equivalent job is done by the CNI plugin.

Worth knowing the shape of, rarely worth reaching for now — a multi-host Docker deployment in 2026 is usually a signal you wanted an orchestrator.

Publishing, precisely

bash
-p 8080:80              # all interfaces — public
-p 127.0.0.1:8080:80    # localhost only
-p 80                   # random host port

Gotcha: -p 8080:80 binds 0.0.0.0, and Docker writes its own iptables rules that bypass a host firewall configured with ufw. A database “protected by the firewall” but published this way is reachable from the internet. Bind to 127.0.0.1 for anything that should not be public.

Talking to the host

From inside a container, the host is host.docker.internal on Docker Desktop, and on Linux the gateway address of the bridge — or add --add-host=host.docker.internal:host-gateway to get the same name everywhere. Hardcoding localhost in a container to reach a host service is a frequent early mistake: localhost is the container.

Interview angle 5

  • “What are the network modes?” - bridge (default, isolated network with port publishing), host (shares the host stack, no isolation and no port mapping), none (no networking), and overlay for multi-host. Bridge is the default for good reason.
  • “How do containers find each other?” - on a user-defined bridge network, by service name via the embedded DNS. The default bridge doesn’t provide name resolution, which is why Compose creates its own network.
  • “When is host networking justified?” - when you need the host’s exact network stack or want to avoid the NAT hop for latency-sensitive or high-throughput workloads. The cost is losing isolation and port-conflict safety.
  • “Does publishing a port respect the host firewall?” - not by default. Docker inserts its own iptables rules ahead of ufw, so -p 5432:5432 can expose a database you believed was firewalled. Publish to 127.0.0.1 when the service is internal.
  • “How does a container reach a service on the host?” - host.docker.internal, or the bridge gateway on Linux with --add-host=host.docker.internal:host-gateway. Not localhost — inside the container that is the container.