Container Networking Basics
Container networking looks complicated at first because there are five different network modes and they behave differently. In practice, the choice is usually between three: bridge (the default, NAT-based), host (shares the host's network directly), and macvlan (container is a real device on the LAN). The right choice depends on what the container needs to do and who needs to reach it.
The four Docker network modes
| Mode | Container's IP | Reachable from LAN? | Best for |
|---|---|---|---|
| bridge (default) | Private (172.17.0.x on docker0) | Only via published ports on host IP | Most services; default for good reason |
| host | Host's IP | Yes, on the container's listening ports | Performance-sensitive workloads; low-overhead networking |
| macvlan | LAN IP (e.g., 192.168.1.x) | Yes, as a real LAN device | Containers that need their own IP on the LAN |
| none | No network | No | Isolated batch jobs; security-sensitive single-purpose containers |
Bridge mode in detail
Default for Docker. The host has a Linux bridge named docker0 (or a custom user-defined bridge). Each container:
- Gets a virtual Ethernet pair: one end inside the container's namespace as eth0, the other attached to the bridge.
- Receives a private IP via Docker's built-in DHCP (typically 172.17.x.x for docker0, custom range for user-defined bridges).
- Reaches outside via NAT through the host (the host's iptables rules implement source NAT).
- Can be reached from outside only via published ports —
-p 8080:80forwards host's TCP 8080 to container's TCP 80.
For multi-container setups, user-defined bridges are preferred over the default docker0 because they provide automatic DNS resolution between containers by container name.
Host mode
The container shares the host's network namespace entirely:
- No virtual NIC, no bridge, no NAT, no port mapping.
- Container's listening ports are on the host's IP at those exact ports.
- Container sees the same interfaces and IPs the host does.
Use cases:
- Highest network performance (no NAT or bridge overhead).
- Services that need access to many host ports (like a monitoring agent collecting from various local services).
- Services that need raw network access (like network scanners, packet captures).
Drawbacks: no isolation between container's network and host's. Cannot bind to a port the host is already using.
Macvlan mode
The container gets its own MAC address and an IP on the LAN — appearing to the rest of the network as a separate device:
- Container's interface is attached directly to the host's physical NIC via the macvlan driver.
- Container gets an IP via DHCP from the LAN router or via static configuration.
- Other devices on the LAN can reach it directly by IP, no port forwarding needed.
Use cases:
- Pi-hole listening on port 53 (where the host can't use 53 simultaneously).
- Home Assistant doing mDNS-based device discovery (needs to be on the LAN broadcast domain).
- Any container that wants to look like a "real" device to the rest of the network.
Drawback: by default, macvlan containers cannot reach the host (and vice versa). Workaround: create a macvlan sub-interface on the host. Some Wi-Fi APs block the multiple MACs that macvlan introduces; this works best on wired networks.
User-defined bridges
Beyond the default docker0, you can create custom bridges:
docker network create mynet
docker run --network mynet --name myapp ...
Benefits over default docker0:
- Automatic DNS — containers on the same user-defined bridge can resolve each other by name.
- Better isolation — containers on different user-defined bridges can't reach each other unless explicitly connected.
- Configurable subnet and gateway.
Best practice: always use user-defined bridges instead of the default docker0 for production.
Docker Compose networking
By default, docker-compose creates a user-defined bridge for the services in a compose file. Services can reach each other by service name:
services:
web:
image: nginx
db:
image: postgres
# web can reach db at "db:5432"
No need to publish the db port unless you want to access it from outside the compose stack.
Overlay networks
For multi-host setups (Docker Swarm, Kubernetes), overlay networks let containers on different hosts communicate as if on the same network. Traffic is encapsulated in VXLAN and transmitted between hosts via UDP.
For single-host homelab, overlay isn't needed — bridge or macvlan is sufficient.
Kubernetes networking model
Kubernetes mandates:
- Every pod gets its own IP.
- Pods can communicate without NAT.
- Nodes can communicate with pods without NAT.
- The IP a pod sees is the IP others see for it.
CNI plugins implement this. Calico uses BGP for routing; Cilium uses eBPF; Flannel uses overlay; Weave uses overlay. The model is more sophisticated than Docker's default but conceptually similar — containers are first-class network citizens with their own IPs.
Port publishing
Bridge-mode containers expose themselves to outside via port publishing:
docker run -p 8080:80 nginx # host:container
docker run -p 127.0.0.1:8080:80 nginx # bind only to localhost
docker run -p 8080:80/udp nginx # UDP instead of TCP
Without -p, the container is reachable only from the host's bridge network, not from outside.
DNS inside containers
Containers use the host's /etc/resolv.conf by default. For user-defined bridges, Docker also provides an internal DNS at 127.0.0.11 that resolves container names. For Kubernetes, CoreDNS provides cluster-internal DNS.
Common networking issues
- Container can't reach external internet. Check NAT iptables rules; check the host's IP forwarding (
net.ipv4.ip_forward=1). - Port already in use. Another process on the host is bound to the same port. Use a different host port.
- Containers on different compose stacks can't talk. They're on different user-defined bridges. Use
docker network connectto bridge them or move them to the same external network. - Container sees the wrong DNS. Set
--dnsat run time or in compose. - macvlan container can't reach the host. Default macvlan behavior. Create a macvlan sub-interface on the host.
Frequently Asked Questions
What is the default container network mode?
For Docker, it's bridge mode — containers get a private IP on docker0 (a Linux bridge), and outbound traffic is NATed through the host. Each container has its own network namespace; published ports are forwarded from the host's IP to the container's. Other modes (host, macvlan, overlay) are used for specific scenarios.
What is host networking in Docker?
The container shares the host's network namespace directly — no bridge, no NAT, no port mapping. The container's listening ports are exposed on the host's IP at those exact ports. Best performance, simplest networking, but the container has no network isolation from the host and cannot reuse ports already in use.
When should I use macvlan?
When you want the container to appear as a separate device on the LAN with its own MAC address and its own IP on the LAN subnet. Used in homelabs for containers that need to be on the LAN directly (Pi-hole listening on port 53, Home Assistant for device discovery, anything that benefits from bypassing NAT). Constraints: the host's network mode must allow promiscuous, and some Wi-Fi APs block this.
What is an overlay network?
A virtual network that spans multiple host machines, allowing containers on different hosts to communicate as if on the same network. Implemented by encapsulating container-to-container traffic in VXLAN or similar tunneling. Used in Docker Swarm and Kubernetes for multi-host clusters.
How does Kubernetes networking differ from Docker?
Kubernetes mandates that every pod gets its own IP and that any pod can reach any other pod without NAT — the "flat IP space" model. The CNI (Container Network Interface) plugins (Calico, Cilium, Flannel, Weave) implement this in different ways, typically using overlay networks or BGP routing. Much more sophisticated than Docker's default bridge.
Related Guides
More From This Section
All Homelab Guides
Proxmox, pfSense vs OPNsense, Docker vs VMs, VLANs, and self-hosted apps.
DNS for Homelab
How to run DNS for a homelab — local-only domain names, split-horizon between internal and external resolution, Pi-hole…
Docker vs Virtual Machines in a Home Lab
Docker containers share the host kernel and start fast; VMs boot a full OS with stronger isolation.
Run a Speed Test
Measure download, upload, ping, and jitter in your browser.