Host Network #
Among all the network drivers Docker offers, host is the simplest conceptually — and the most controversial in its implications. When a container runs with --network host, it has no network namespace of its own. The container uses the host’s network stack directly: the host’s eth0 interface, the host’s port 80, the host’s routing table, everything. No NAT, no bridge, no port mapping. The container is a “first-class citizen” on the host network.
The immediate implication: the container loses one of Docker’s main security features — network isolation. But in return, you get the best network performance and access to all host interfaces. For some workloads, this trade-off is well worth it. For others, it’s a serious anti-pattern.
This article covers host networking in depth: how it works at the OS level, when to use it (and when never to use it), the performance vs isolation trade-off, and production usage patterns. By the end, you’ll be able to make the right architectural decision for your case.
What Is Host Networking? #
Host networking is a mode where the container doesn’t create a new network namespace. It runs in the host namespace — the same network namespace as the host processes themselves.
flowchart TB
subgraph HOST["Docker Host - Network Namespace"]
H_ETH0[eth0: 192.168.1.10]
H_LO[lo: 127.0.0.1]
H_PORT[Ports 80, 443, 3000, etc.]
subgraph CT1["Container A (host net)"]
C_ETH0[eth0: 192.168.1.10 - same as host]
C_PORT[Port 80 - same as host]
end
subgraph CT2["Container B (host net)"]
C_ETH0B[eth0: 192.168.1.10 - same as host]
C_PORTB[Port 8080 - same as host]
end
endMain characteristics:
- The container shares the network stack with the host.
- The container sees the host IP as its own (
localhost= the host’s localhost,eth0= the host’s eth0). - Container ports = host ports — port 80 in the container = port 80 on the host. No port mapping.
- No NAT, no bridge, no veth — direct connection to the physical network.
- No network isolation — containers can bind to the same ports as the host, and they’ll conflict.
Port conflicts are the main risk. If the host already runs nginx on port 80, you can’t run a host-network container that also listens on port 80. The second container will crash with “address already in use”.
How It Works at the OS Level #
To understand host networking, you first need to understand network namespaces — a concept covered in the Overview article. On Linux, every process runs inside one or more namespaces. Network namespaces separate interfaces, routing tables, and iptables rules.
# List existing network namespaces
ip netns list
# (empty for normal containers - they're in anonymous namespaces)
# Check the network namespace of a host-network container
docker run --rm --network host alpine ip netns identify
# Will error or return "host" - the container is in the same namespace
# See what processes are in the host namespace
sudo ls -la /proc/1/ns/net
# A host-network container will symlink to the same file
flowchart LR
subgraph Normal["Normal Container (bridge)"]
NS_C[Namespace: container-xyz]
ETH_C[eth0: 172.17.0.2]
VETH[veth pair]
end
subgraph Host["Host Network Container"]
NS_H[Namespace: same as host]
ETH_H[eth0: 192.168.1.10]
PHY[Host physical eth0]
end
Normal --> VETH --> BR[bridge docker0]
Host --> PHYIn bridge mode, Docker creates a new namespace, virtual interfaces (veth), and a bridge to connect the container. In host mode, none of that exists. The container “borrows” the host namespace directly.
This also explains why port mapping is impossible in host networking: port mapping needs iptables DNAT to forward traffic from a host port to the container. But in host networking, traffic on port 80 is already directly handled by the process in the container — nothing to forward.
How to Run a Container with Host Networking #
# CLI way
docker run -d --network host nginx
# Docker Compose
services:
nginx:
image: nginx
network_mode: host
Verifying a container runs on the host network:
# Check the container IP - must equal the host's
docker run --rm --network host alpine ip addr show eth0
# Check the ports the container listens on
docker run --rm --network host nginx &
sleep 1
ss -tlnp | grep 80
# nginx will appear in the host namespace
On macOS and Windows Docker Desktop, host networking doesn’t actually use the host network. Docker Desktop runs in a Linux VM (because containers need a Linux kernel), and “host networking” is the host network of that VM — not your laptop’s. This often tricks developers. For real host-network testing, you need native Linux.
Comparison with Other Network Modes #
| Aspect | host | bridge | none |
|---|---|---|---|
| Network namespace | Shared with host | Separate | No interfaces |
| IP address | Host IP | Private bridge IP | Loopback only |
| Internet access | ✅ Direct | ✅ Via NAT | ❌ |
| Host access | ✅ Direct (localhost = host) | ❌ Requires port mapping | ❌ |
| Port mapping | ❌ Not possible | ✅ -p | ❌ |
| Network performance | Maximum | Standard (NAT overhead) | — |
| Isolation | None | Per bridge | Maximum |
| Best for | High-perf, monitoring | Multi-container apps | Sandboxes |
Bridge with NAT and bridge forwarding adds a small but measurable overhead. For thousands of connections per second, this difference can be significant. Host removes all that overhead.
When to Use Host Networking #
1. High-Throughput Reverse Proxies #
Nginx or Traefik handling thousands of requests per second. NAT and bridge overhead can be felt.
services:
nginx:
image: nginx:alpine
network_mode: host
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
Industry best practice: For high-traffic production, Traefik or HAProxy on host networking is a common pattern. They don’t need isolation, and they must be the “main door” — efficiency here matters a lot.
2. Network Monitoring & Sniffing #
Tools like Wireshark, tcpdump, or intrusion detection systems need access to all traffic on the host. Host networking enables this.
# A container with tcpdump that can sniff all host traffic
docker run -it --rm --network host --cap-add=NET_ADMIN nicolaka/netshoot tcpdump -i any
3. DNS or DHCP Servers #
Containers that must bind to port 53 (DNS) or 67/68 (DHCP). These ports are often handled directly by host daemons (systemd-resolved), and host networking makes integration easier.
4. Service Discovery Tools #
Consul agents, etcd, or the Prometheus node exporter — usually run on host networking to collect metrics from the host itself.
services:
node-exporter:
image: prom/node-exporter
network_mode: host
pid: host # so it can also read host processes
5. Game Servers or Real-Time Applications #
Game servers (Minecraft, Counter-Strike, etc.) need the lowest possible latency. NAT and bridges add microseconds that can be felt in gameplay.
docker run -d --network host \
-e EULA=TRUE \
itzg/minecraft-server
6. BuildKit or CI/CD #
Docker-in-Docker (DinD) often needs host networking so build caches and local registries can be accessed without overhead.
When Host Networking Should Never Be Used #
1. Multi-Tenant Environments #
If the host serves many users or projects, host networking lets a container listen to traffic from other containers/processes on the host. This is a serious isolation violation.
2. Production Microservices #
Modern microservice applications usually consist of many services. If all of them use host networking, port conflicts become a nightmare.
# ✗ Anti-pattern: every service uses host networking
service_a (port 8080)
service_b (port 8080) # CONFLICT!
# ✓ Solution: bridge network + port mapping
service_a -p 8080:8080
service_b -p 8081:8080
# No conflict
3. Databases or Sensitive Services #
Postgres, MySQL, Redis, MongoDB — services storing sensitive data. Host networking exposes them to all traffic on the host, and if another container runs malicious code, it can directly access the database.
# ✗ Anti-pattern: database on host networking
services:
postgres:
image: postgres
network_mode: host
# Host port 5432 = container port 5432 = accessible to every process on the host
# ✓ Solution: internal bridge network
services:
postgres:
image: postgres
networks:
- backend
api:
image: my-api
networks:
- backend
depends_on:
- postgres
networks:
backend:
internal: true
4. Standard Multi-Container Applications #
For ordinary web apps, API + database + cache, bridge networking is the safer, sufficiently performant default.
Host Networking Security Implications #
Because the container shares the network namespace with the host, the security implications are serious:
flowchart TB
CT[Container: host network] -->|sees all processes| PS[Host processes]
CT -->|can bind to any port| PORT[All host ports]
CT -->|can sniff traffic| SNIFF[All host traffic]
CT -->|bypasses firewall| FW[Host iptables - same as container]
subgraph Host["Host"]
PS
PORT
SNIFF
FW
end- Process visibility — without
--pid=host, the container only sees its own processes. But withnetwork=hostalone, it has access to all host networking. - Port binding — the container can bind to any port on the host, including already-used ones. Crash or port takeover.
- Traffic sniffing — with
CAP_NET_RAWortcpdump, the container can sniff all host traffic, including HTTPS (well, it can’t read content, but it can see metadata). - Firewall bypass — Docker’s iptables rules don’t apply. The container is truly a host citizen.
Run host-network containers only with images you trust. Random Docker Hub images, especially from unclear publishers, should never be run with --network host. Such an image could sniff data, bind to the host’s SSH port, or perform lateral movement to other host services.How to Secure Host Networking #
If you must use host networking, there are several mitigations:
# 1. Drop unneeded capabilities
docker run --network host --cap-drop=ALL --cap-add=NET_BIND_SERVICE nginx
# 2. Run as a non-root user
docker run --network host --user 1000:1000 my-app
# 3. Use a minimal image (alpine, distroless)
docker run --network host nginx:alpine
# 4. Read-only filesystem
docker run --network host --read-only nginx
# 5. Avoid mounting sensitive directories
# DON'T mount /proc, /sys, /var/run/docker.sock
Worst case: a container with --network host -v /var/run/docker.sock:/var/run/docker.sock. This gives the container full access to the Docker daemon — it can spawn other containers, read images, or even delete everything. Avoid this combination unless you truly understand the implications (e.g. for management tools like Portainer).Host Networking and Docker Compose #
In Docker Compose, host networking is declared with network_mode:
version: "3.9"
services:
proxy:
image: traefik:v3
network_mode: host
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./traefik.yml:/etc/traefik/traefik.yml:ro
command:
- "--providers.docker=true"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
You can also mix: some services on host networking, others on bridge.
services:
# Traefik on host - the entry point
proxy:
image: traefik
network_mode: host
# Backend services on an internal network
api:
image: my-api
networks:
- internal
db:
image: postgres
networks:
- internal
networks:
internal:
internal: true
This pattern is very common in production: Traefik/Nginx on host networking for performance, backend services on an internal bridge network for security. Traefik becomes the only exposed surface.
Monitoring: Bandwidth and Connections in Host Networking #
Because the container shares the network with the host, traditional Docker monitoring (per-container network stats) doesn’t apply. You use host network stats instead.
# View traffic per host interface
iftop -i eth0
nethogs
bmon
# View active connections
ss -tunap
# Container stats
docker stats --no-stream
# For host networking, container Network IO = host's
# Prometheus scrape config for a host-network container
scrape_configs:
- job_name: 'node-exporter'
static_configs:
- targets: ['localhost:9100'] # node-exporter runs on the host
Anti-Patterns: Signs You’re Using Host Networking Wrong #
# ✗ Anti-pattern 1: database on host networking
docker run -d --network host postgres
# Postgres is exposed to all host interfaces
# ✗ Anti-pattern 2: too many services on host networking
docker run -d --network host service-a
docker run -d --network host service-b
# Port conflict waiting to happen
# ✗ Anti-pattern 3: untrusted image on host networking
docker run -d --network host some-random-image-from-internet
# Very high security risk
# ✗ Anti-pattern 4: forgetting that host networking disables iptables isolation
docker run -d --network host --publish 8080:80 nginx
# Port 8080 is ignored! The container listens directly on host port 80
When to Move Away from Host Networking #
Use these signs as a guide:
| Sign | Action |
|---|---|
| Port conflicts between containers | Move to bridge networking + mapping |
| Untrusted images | NEVER use host networking |
| Multi-tenant host | Always bridge/specific networks |
| Need per-container granular monitoring | Bridge, not host |
| Traffic sniffing required | --cap-add=NET_RAW on bridge also works |
Benchmark: How Big Is the Host vs Bridge Difference? #
The claim “host networking is faster” is often made but rarely measured. Here’s a simple benchmark you can reproduce yourself.
# Install the tool
docker run --rm --network host alpine apk add wrk
docker run --rm --network bridge alpine apk add wrk
# Run nginx
docker run -d --name nginx-host --network host nginx
docker run -d --name nginx-bridge --network bridge -p 8080:80 nginx
# Benchmark host
wrk -t4 -c100 -d30s http://localhost:80
# Benchmark bridge (in a second terminal)
wrk -t4 -c100 -d30s http://localhost:8080
In common tests, the throughput difference between host and bridge for HTTP is small (10–30%), but latency on host networking can be 30–50% lower because there’s no extra NAT hop.
flowchart LR
A[Client] -->|1 hop| B[Bridge]
B -->|DNAT| C[Container]
C --> B
B --> A
A2[Client] -->|0 hops| C2[Container on host net]
C2 --> A2For latency-sensitive workloads (financial trading, real-time gaming, video streaming), this difference is crucial. For ordinary web apps, it’s hard to notice.
Note: in production with HTTPS, the host vs bridge difference shrinks because TLS overhead dominates. But for internal services (HTTP/2, gRPC, message brokers), host networking still wins significantly.
Summary #
- Host networking = the container shares the network namespace with the host. No bridge, NAT, veth, or port mapping. The container sees the host IP, host ports, and host interfaces.
- Best performance, but isolation is lost. The main trade-off: performance vs security.
- Good for: high-throughput reverse proxies, network monitoring, DNS/DHCP servers, game servers, real-time apps, service discovery agents.
- Bad for: multi-tenancy, many-service microservices, sensitive databases, untrusted images, standard multi-container applications.
- Security risks: the container can sniff traffic, bind to any port, bypass Docker’s iptables firewall. Run only trusted images with minimum capabilities.
- Default port conflicts: two host-network containers can’t bind the same port. This isn’t a feature, it’s a common trap.
- Docker Desktop (macOS/Windows) doesn’t truly use host networking — containers run in a Linux VM, not on your laptop. For real testing, use native Linux.
- A common production pattern: Traefik on host networking + backends on an internal bridge. Efficient entry point, secure backend.
- Anti-patterns: databases on host networking, all services on host networking, random images on host networking, forgetting that
-pis ignored with host networking.- Monitoring host-network containers = monitoring the host. Per-container network stats aren’t available.
← Previous: NAT (Network Address Translation) Next: None Network →