| |

Docker 33 🐳 Host Networking (–net=host): Performance, Security, and Port Collisions

The host network driver removes the network namespace from the container. The container shares the host’s network stack directly, with the host’s IP address, the host’s interfaces, and the host’s ports. There is no NAT, no virtual bridge, and no port mapping. The container’s application binds to the host’s port directly, and the performance is the host’s performance. This is the driver for the cases where the network isolation is a cost rather than a feature, and where the cost is worth paying.

Key point: With --net=host, the container does not get its own IP address. It shares the host’s network namespace, which means it has the host’s IP and binds to the host’s ports directly. The -p and --publish flags are ignored, and a warning is printed. The performance is the best because there is no NAT and no userland proxy. The isolation is the worst because the container can see and use every network interface and port on the host.


Why host networking exists

The performance problem. The bridge driver adds a layer of NAT. Every packet from the container is rewritten, and every packet to the container is forwarded through a proxy. The NAT and the proxy have a cost. The host driver removes both. The container’s traffic goes directly through the host’s interfaces, and the performance is the host’s performance . For the latency-sensitive applications—high-frequency trading, real-time communication, gaming servers—the difference matters.

The port-range problem. A container on a bridge network must publish each port explicitly with -p. A container that needs a large range of ports, or that binds ports dynamically, cannot use the bridge without publishing the whole range. The host driver removes the problem: the container binds any port the host can bind, and the port is available immediately .

The monitoring problem. A network monitoring tool needs to see all the traffic on the host’s interfaces. A container on a bridge sees only its own virtual interface. A container on the host network sees the host’s interfaces, including the promiscuous mode captures that the monitoring tools require .

The legacy problem. A legacy application that expects to run directly on the host, that binds to a specific interface, or that uses raw sockets cannot run on a bridge network without changes. The host driver makes the container’s network environment identical to the host’s, and the legacy application runs without modification.

The simplicity problem. The host driver has no port mapping to configure, no bridge to manage, and no NAT rules to inspect. The container binds the port, and the port is available. The configuration is the absence of configuration.


a. The performance: no NAT, no proxy

The host driver’s performance advantage is the absence of the NAT and the userland proxy .

The bridge driver’s data path:

  1. The container sends a packet to the bridge.
  2. The host’s iptables rules rewrite the source address (SNAT).
  3. The packet goes out the host’s interface.
  4. The return packet arrives.
  5. The iptables rules rewrite the destination address (DNAT).
  6. The packet goes to the container.

The host driver’s data path:

  1. The container sends a packet out the host’s interface.
  2. The return packet arrives.

The bridge path has the additional translation steps. The translation is fast, but it is not free. For most applications, the difference is measured in microseconds. For the latency-sensitive applications, the microseconds matter.

A benchmark of the two modes shows the difference: the bridge network’s response time is measured at 0.012s, and the host network’s at 0.004s for the same request . The difference is the NAT and the proxy.

The research on the topic is consistent: with the proper tuning, the host mode achieves the bare-metal performance. The network I/O performance without Docker and with the Docker host networking mode are identical when the application is properly configured .

The performance is the reason the host driver exists. The isolation is the cost.


b. The security: no isolation, full host access

The host driver removes the network isolation. The container can see every network interface on the host, including the internal network, the VPN, and the management interfaces . The container can bind any port, including the ports that the host’s services use. The container can capture the traffic on the host’s interfaces if it has the CAP_NET_RAW capability.

The security implications are concrete. A vulnerability in the container’s application can be exploited to attack the host’s network, because the container has the host’s network access . A container that is compromised can bind a port that the host’s legitimate service uses, and the service is disrupted. A container that is compromised can capture the traffic that the host’s other services send and receive.

The host mode is a deliberate trade-off: the performance for the isolation. The trade-off is appropriate when the container is trusted, when the performance is critical, and when the isolation is not required. The trade-off is inappropriate when the container runs untrusted code, when the host is multi-tenant, and when the network isolation is a security requirement.

The mitigations are the least privilege and the monitoring. The --cap-drop=NET_RAW removes the packet capture capability from the container . The network monitoring detects the anomalous traffic from the container. The container’s privileges are limited, and the container’s network behavior is observed.

The Docker Desktop’s host networking has additional limitations. It works on layer 4 only, so the protocols below TCP and UDP are not supported. It does not work with the Enhanced Container Isolation enabled, because the isolation and the host network access contradict each other .


c. The port collisions

The host driver’s port space is the host’s port space. If the host’s service is listening on port 80, a container on the host network cannot bind port 80. The collision is not resolved automatically. The container’s application fails to start with the “address already in use” error .

The collision is more likely than it seems. The host’s services—the web server, the DNS resolver, the SSH server—bind the well-known ports. The container’s application that binds the same port collides. The container’s application that binds a port in the ephemeral range may collide with the outbound connections that the host’s kernel uses for the source ports .

The net.ipv4.ip_local_port_range sysctl defines the ephemeral range. The kernel uses the range for the source ports of the outbound connections. A container that binds a port in the range may find the port transiently held by an unrelated process’s outbound connection . The “address already in use” error appears intermittently, and the cause is not obvious.

The port mapping is ignored on the host network. The -p and --publish flags produce a warning: “Published ports are discarded when using host network mode” . The container’s application binds the port it wants, and the port is the host’s port.

The port collision is the diagnostic challenge. The ss -tlnp command shows which process holds the port. The lsof -i :port command is the alternative. The docker ps -a command shows which containers are running and which ports they publish. The collision may be with the host’s process, with another container, or with an orphaned iptables rule .


Complete Example Session

# ============================================
# PART 1: BASIC HOST NETWORK
# ============================================
docker run -d --name web --network host nginx
curl http://localhost:80
# ============================================
# PART 2: PORT MAPPING WARNING
# ============================================
docker run -d --name web -p 8080:80 --network host nginx
# WARNING: Published ports are discarded when using host network mode
# ============================================
# PART 3: PORT COLLISION
# ============================================
docker run -d --name web --network host nginx
# If the host already uses port 80, the container fails
# ============================================
# PART 4: CHECK THE PORT
# ============================================
sudo ss -tlnp | grep :80
sudo lsof -i :80
# ============================================
# PART 5: ACCESS THE HOST FROM THE CONTAINER
# ============================================
docker run --rm -it --network host nicolaka/netshoot
nc localhost 80
# ============================================
# PART 6: PERFORMANCE COMPARISON
# ============================================
# Bridge: time curl http://container-ip
# Host: time curl http://localhost
# ============================================
# PART 7: SECURITY HARDENING
# ============================================
docker run -d --name web --network host --cap-drop=NET_RAW nginx
# ============================================
# PART 8: DOCKER DESKTOP
# ============================================
# Settings → Resources → Network → Enable host networking
# Then:
docker run -d --name web --network host nginx
# ============================================
# PART 9: THE CONTAINER BINDS THE PORT
# ============================================
docker run -d --name web --network host nginx
docker exec web ss -tlnp
# ============================================
# PART 10: THE HOST NETWORK IS THE HOST'S NETWORK
# ============================================
docker run --rm --network host alpine ip addr
# Shows the host's interfaces

The ten parts covered the basic host network, the port mapping warning, the port collision, the port check, the host access from the container, the performance comparison, the security hardening, the Docker Desktop, the container’s port binding, and the host’s interfaces.


Quick Reference

Host Network Characteristics

AspectValue
IP addressHost’s IP
PortsHost’s ports
NATNone
Userland proxyNone
PerformanceBest
IsolationNone
Port mappingIgnored
PlatformLinux, Docker Desktop 4.34+

Host vs Bridge

AspectHostBridge
IPHost’sContainer’s (NAT)
Port bindingDirectVia -p
PerformanceBestGood (NAT overhead)
IsolationNoneHigh
Port conflictsPossibleResolved by mapping
MonitoringSees all host trafficSees own traffic

Use Cases

Use CaseReason
High-frequency tradingLatency-sensitive
Real-time communicationThroughput-critical
Network monitoringNeeds all host traffic
Legacy applicationsExpects host network
Large port rangesCannot publish all ports

Security Hardening

MeasureEffect
--cap-drop=NET_RAWPrevents packet capture
Monitor trafficDetects anomalies
Trust the containerThe fundamental requirement
Avoid untrusted codeThe isolation is gone

Port Collision Commands

CommandPurpose
ss -tlnp | grep :portWhich process holds the port
lsof -i :portAlternative check
docker ps -aWhich containers are running
iptables -t nat -L DOCKEROrphaned DNAT rules

Best Practices

✅ Do This:

# Use host network for performance-critical applications
docker run -d --network host myapp                              # ✅

# Drop the NET_RAW capability
docker run -d --network host --cap-drop=NET_RAW myapp          # ✅

# Check the port before starting
sudo ss -tlnp | grep :80                                       # ✅

# Use the host network when the container needs many ports
docker run -d --network host myapp                              # ✅

# Enable host networking on Docker Desktop
# Settings → Resources → Network → Enable host networking       # ✅

# Monitor the container's network behavior
docker logs myapp                                              # ✅

❌ Don’t Do This:

# Don't use host network for untrusted code
docker run --network host untrusted-image                       # ❌

# Don't use -p with host network
docker run -p 8080:80 --network host nginx                     # ⚠️ ignored

# Don't use host network when isolation is required
docker run --network host multi-tenant-app                      # ❌

# Don't assume the port is available
docker run --network host nginx  # if port 80 is used          # ⚠️

# Don't use host network on Windows containers
docker run --network host myapp  # not supported                # ❌

# Don't use host network with Enhanced Container Isolation
# The two contradict each other                                 # ❌

Common Pitfalls

PitfallWhy It HappensFix
Port collisionHost’s port in useCheck ss, use different port
-p ignoredHost networkRemove the flag
No isolationHost networkUse bridge if isolation needed
Container sees host’s networkHost networkExpected behavior
Docker Desktop not workingFeature not enabledEnable in Settings
Windows container failsNot supportedUse Linux container
Ephemeral port collisionPort in rangeUse a port below the range

Real-World Examples

1. Basic Host Network

docker run -d --network host nginx

2. Port Collision

sudo ss -tlnp | grep :80
docker run --network host nginx  # fails if port 80 in use

3. Security Hardening

docker run -d --network host --cap-drop=NET_RAW nginx

4. Host Access

docker run --rm -it --network host alpine nc localhost 80

5. Performance Test

time docker run --rm --network host appropriate/curl http://localhost/

6. Docker Desktop

# Enable in Settings → Resources → Network
docker run -d --network host nginx

7. Check Interfaces

docker run --rm --network host alpine ip addr

8. Check Ports

docker exec web ss -tlnp

9. Legacy App

docker run -d --network host legacy-app

10. Monitoring

docker run -d --network host --cap-add=NET_RAW nicolaka/netshoot tcpdump -i eth0

Visual

Host Network

┌─────────────────────────────────────────────────────────────┐
│  HOST (192.168.1.10)                                        │
│  ┌─────────────────────────────────────────────────────┐    │
│  │  eth0: 192.168.1.10                                 │    │
│  │  Container shares the host's network stack          │    │
│  │  Container binds port 80 on the host's IP           │    │
│  └─────────────────────────────────────────────────────┘    │
│                                                             │
│  No isolation. No NAT. No proxy. Maximum performance.       │
│                                                             │
└─────────────────────────────────────────────────────────────┘

Performance Comparison

┌─────────────────────────────────────────────────────────────┐
│  BRIDGE NETWORK                                             │
│                                                             │
│  Container → veth → docker0 → iptables (SNAT) → eth0        │
│  eth0 → iptables (DNAT) → docker0 → veth → Container        │
│                                                             │
│  NAT adds latency.                                          │
│                                                             │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  HOST NETWORK                                               │
│                                                             │
│  Container → eth0 → outside                                 │
│  outside → eth0 → Container                                 │
│                                                             │
│  No NAT. No proxy. Bare-metal performance.                  │
│                                                             │
└─────────────────────────────────────────────────────────────┘

Port Collision

┌─────────────────────────────────────────────────────────────┐
│  HOST: nginx listening on port 80                           │
│                                                             │
│  docker run --network host nginx                            │
│    │                                                        │
│    ▼                                                        │
│  Container tries to bind port 80                            │
│    │                                                        │
│    ▼                                                        │
│  "address already in use"                                   │
│                                                             │
│  The host's port and the container's port are the same.     │
│                                                             │
└─────────────────────────────────────────────────────────────┘

Security Trade-off

┌─────────────────────────────────────────────────────────────┐
│  BRIDGE                                                     │
│                                                             │
│  Container sees: its own network namespace                  │
│  Container can reach: the published ports                   │
│  Host is protected by the namespace isolation               │
│                                                             │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  HOST                                                       │
│                                                             │
│  Container sees: every interface on the host                │
│  Container can reach: every port on the host                │
│  Host is exposed to the container's network access          │
│                                                             │
│  The isolation is the cost. The performance is the benefit. │
│                                                             │
└─────────────────────────────────────────────────────────────┘

Summary

ItemValue
Flag--network host or --net=host
IP addressHost’s IP
PortsHost’s ports
NATNone
Userland proxyNone
PerformanceBest
IsolationNone
Port mappingIgnored
PlatformLinux, Docker Desktop 4.34+
Security riskHigh

Key takeaways:

  • The host driver removes the network namespace. The container shares the host’s network stack, which means it has the host’s IP and binds to the host’s ports directly. The -p and --publish flags are ignored .
  • The performance is the best because there is no NAT and no userland proxy. The bridge driver’s NAT and proxy add latency, and the host driver removes both. The research shows the bare-metal performance is achievable with the proper tuning .
  • The isolation is the worst. The container sees every interface on the host, including the internal network, the VPN, and the management interfaces. A compromise of the container is a compromise of the host’s network access .
  • The port collisions are possible. The container’s port space is the host’s port space. If the host’s service uses the port, the container cannot bind it. The ss and lsof commands show which process holds the port .
  • The security hardening is the least privilege and the monitoring. The --cap-drop=NET_RAW removes the packet capture capability. The network monitoring detects the anomalous traffic. The container must be trusted .
  • The Docker Desktop’s host networking is the opt-in feature. It works on version 4.34 and later, and it requires the feature to be enabled in the settings. It does not work with the Enhanced Container Isolation .
  • The host network is for the cases where the isolation is a cost, not a feature. The performance-critical applications, the legacy applications, the monitoring tools, and the applications that need a large range of ports. The trade-off is explicit: the performance for the isolation.

Remember: The host network driver is the maximum performance and the minimum isolation. The container shares the host’s network stack, which means the container’s traffic is the host’s traffic, and the container’s ports are the host’s ports. The NAT and the proxy are gone, and the performance is the bare metal. The security is the trade-off: the container can see and use every interface on the host. Use the host driver when the performance is critical and the container is trusted. Use the bridge driver when the isolation is required and the performance is sufficient. And remember the port collisions: the host’s port is the container’s port, and the two cannot share the same number.



Stop using slow, ad-bloated tool sites! 🤮

🔎 Search “KandZ Tools” on Google to use many professional utilities for free.

KandZ.me is the ultimate minimalist hub for:
✅ Finance (Mortgage, Interest, Inflation)
✅ Tech (Base64, JSON, Dev Suite, IP)
✅ Health (BMI, BMR, TDEE)
✅ Productivity (Timer, Workspace, QR)

⚡️ Fast & Private
🔒 No data leaves your device
💎 100% Free

🔗 Use it now: https://tools.kandz.me
🔖 Bookmark it—you’ll need it later!