network_mode: host in Docker Compose Explained
Home Assistant or Pi-hole goes into a docker-compose.yml, the stack comes up healthy, and device discovery still doesn't work -- no new devices show up. The forum fix is network_mode: host. What it actually does, when it's worth the isolation you give up, and when bridge is still right.

You put Home Assistant or Pi-hole into a docker-compose.yml, brought the stack up, and device discovery just doesn't work. No new devices show up, no auto-detected integrations, nothing. The container is running fine — docker compose ps shows it healthy — it just can't see the rest of your LAN. The fix that keeps showing up in forum threads is network_mode: host, and it sounds like it might break the isolation you actually wanted from Docker in the first place.
TL;DR
network_mode: hostremoves the container's own network stack and gives it the host machine's network interface directly — no separate IP, no NAT, no port mapping.- It matters most for services that rely on multicast-based discovery (mDNS/Zeroconf, SSDP/UPnP) — those broadcasts generally don't survive Docker's default bridge network, because the bridge NATs the container behind the host's IP.
- Historically Linux-only; Docker Desktop 4.34+ added support, but you have to switch it on yourself in Settings → Resources → Network, and it still only applies to Linux containers.
ports:is not just unnecessary undernetwork_mode: host— combining the two is a Compose config error, because host mode already exposes the container's ports directly on the host.- Most services (web apps, APIs, databases) have no discovery dependency — for those, bridge's isolation and explicit port mapping are the better default, not a limitation to work around.
Why the Default Bridge Network Blocks Discovery
Compose's default networking puts every service on a bridge network and NATs it behind the host's IP — each container gets its own private address, and Compose maps the ports you explicitly declare. That's normal, deliberate isolation, and it's fine for the majority of services.
It breaks down for anything that depends on multicast to find other devices — mDNS/Zeroconf (the .local hostname resolution and auto-discovery mechanism) and SSDP/UPnP (used by DLNA media servers, some smart-home devices, and Chromecast-style discovery) both broadcast on a multicast address that generally doesn't cross a NAT boundary the way ordinary unicast traffic does. The container can still make outbound connections just fine; it just never sees — or is never seen by — the multicast chatter on your real LAN.
Note
This is exactly the failure mode behind the Home Assistant and Pi-hole discovery complaints you'll find in nearly every self-hosting forum — the container is healthy, the app is running, and it's simply deaf to a class of traffic the bridge network was never designed to forward.
What network_mode: host Actually Does
Per Docker's own host network driver documentation, when a container uses the host driver, "that container's network stack isn't isolated from the Docker host — the container shares the host's networking namespace, and the container doesn't get its own IP address allocated." There's no bridge, no NAT, no separate container IP: the process inside the container binds directly to the host's real network interface, exactly as if it were running outside Docker.
That single change is also why multicast-based discovery starts working again — the container is now genuinely present on your LAN's network segment instead of sitting behind a translated address.
The same Docker documentation is specific about where this driver runs: it supports "Docker Engine on Linux" and, since "Docker Desktop version 4.34 and later," Docker Desktop too — but only after you manually enable it (Settings → Resources → Network → "Enable host networking"), and only for Linux containers; Windows containers are excluded outright. It also doesn't work alongside Docker Desktop's Enhanced Container Isolation feature, since isolating a container from the host and handing it the host's own network are directly contradictory goals.
Bridge vs. Host vs. Macvlan: The Decision
| Network mode | Isolation | Port mapping | Multicast discovery (mDNS/SSDP/UPnP) | Typical use case |
|---|---|---|---|---|
bridge (default) |
Full — container has its own IP, NAT'd behind the host | Explicit, via ports: |
Generally does not work | Web apps, APIs, databases — anything with no LAN-discovery dependency |
host |
None — container shares the host's network stack directly | Not applicable — ports bind straight on the host | Works — container is a real participant on the LAN | Home Assistant, Pi-hole, DLNA/media servers, anything that must see or be seen via multicast |
macvlan |
Container gets its own MAC and IP on the physical LAN, separate from the host's | Not applicable — the container has a real LAN address | Works — container has a genuine LAN presence | Devices that need to look like a distinct physical device on the network, without sharing the host's own IP |
macvlan gets the discovery benefit of host while keeping the container's traffic on its own address rather than the host's — but it needs a network interface the host can put into promiscuous-adjacent mode and usually can't talk to the host itself without extra configuration, which is more setup than most homelab stacks need. For the common case — one or two services that need LAN discovery, sitting on hardware you fully control — host is the simpler choice.
When Host Networking Is Worth It
KEY-STAT: 2 — services running in host mode on my own homelab stack — Home Assistant and Pi-hole, everything else stays on the default bridge network, my homelab
My own homelab runs Home Assistant and Pi-hole under Compose on a Proxmox VM. Home Assistant's device-discovery flow (new Zigbee/Zeroconf devices showing up automatically) never populated anything on the default bridge network — switching that one service to network_mode: host was what made auto-discovery start working at all. Pi-hole has a second, unrelated reason to want it: on bridge networking, Pi-hole's query log shows every client as the same NAT'd container IP instead of each device's real LAN address, which defeats the point of per-client query logging. Host networking fixes both — Pi-hole sees real client IPs, and its own DNS service is directly reachable at the host's IP without a port-mapping detour.
Warning
host networking removes container-level network isolation entirely. A compromised process in a host-mode container has the same network access as a process running directly on the host — every port, every interface, no bridge boundary in between. Reserve it for services where you specifically need that access, not as a default troubleshooting step.
When to Stay on Bridge
Most of a typical Compose stack has no discovery dependency at all — a reverse proxy, a database, a backend API, a static site. None of those need multicast, none of them benefit from host networking, and all of them are safer and more portable on the default bridge with explicit ports: mappings, as covered in our Docker Compose networking explainer. Isolation there isn't a limitation you're working around — it's the feature doing its job.
Setting It Up
services:
homeassistant:
image: ghcr.io/home-assistant/home-assistant:stable
network_mode: host
volumes:
- ./homeassistant-config:/config
restart: unless-stopped
No ports: block, and none is needed — the container's services bind directly to the host's real interfaces. Per the Docker Compose specification, network_mode: host and ports: are explicitly incompatible: "Port mapping must not be used with network_mode: host. Doing so causes a runtime error, because network_mode: host already exposes container ports directly to the host network." Leave an old ports: block in place after switching a service to host mode and Compose will refuse to start it, not silently ignore it.
Tip
once a service is on host networking, it's sharing the host's actual port space — including with every other host-mode container and every process running directly on the host. Two host-mode services (or a host-mode container and a host-installed app) binding the same port will collide immediately, with no Compose-level port remapping available to paper over it. Check what's already listening on a port — ss -tulpn on the host — before adding a second host-mode service that needs it.
FAQ
Does network_mode: host work on Docker Desktop for Mac or Windows?
As of Docker Desktop 4.34, yes — but it must be turned on manually under Settings → Resources → Network → "Enable host networking," it isn't on by default, and it only applies to Linux containers (Windows containers are excluded). Earlier Docker Desktop versions and plain Docker Engine on Linux behave differently: Docker Engine on Linux has always supported it natively with no toggle required.
Can I mix host-networked and bridge-networked services in the same docker-compose.yml?
Yes. `network_mode` is set per service, not globally — most of a stack can stay on the default bridge network while one or two services that need LAN discovery use `network_mode: host`. The tradeoff is that a host-mode service can't be reached from bridge-networked sibling services via the usual Compose service-name DNS the way two bridge services can — it's only reachable via the host's own IP or localhost.
Does host networking improve Docker performance?
It removes one layer of NAT translation, which can matter for very high-throughput or latency-sensitive workloads, but for a typical homelab service the difference is not something you'll notice. The real reason to reach for it is multicast-based discovery (mDNS/SSDP/UPnP) or needing the container to see real client IPs, not raw performance.
Is network_mode: host a security risk on a home network?
It removes Docker's network isolation for that container, so a compromised process gets the same network access as anything else running on the host. On a home LAN behind a router, that's a smaller blast radius than an internet-facing server, but it's still a real tradeoff — use it for the specific services that need LAN discovery, not as a blanket default.
The Bottom Line
network_mode: host trades away Docker's network isolation for direct access to the host's real network interface — the fix for multicast-dependent discovery (mDNS/Zeroconf, SSDP/UPnP) that the default bridge network can't forward, and for services like Pi-hole that need to see actual client IPs instead of a NAT'd container address. Reach for it on the handful of services that specifically need it — Home Assistant, Pi-hole, DLNA-style media servers — and leave everything else, which is most of a typical stack, on the default bridge described in our Docker Compose networking guide. If you're still assembling the rest of the stack around it, our Docker Compose self-hosting guide covers the pieces this one assumes, and our home network security guide covers the wider tradeoffs of exposing services directly on your LAN.
More from Self-Hosting & Privacy

Search results for Tailscale scatter across install guides, pricing pages, and comparisons with no map between them. This hub ties all six — what it is, WireGuard internals, install, exit nodes, pricing, and Headscale — into one decision path from a homelab that runs it.

Added a second person to your tailnet and worried a bill is coming? Tailscale's free Personal plan covers 6 users with unlimited devices per user after the April 2026 rework — the real math on what's actually free and when Standard or Premium pays off.

Tailscale's free tier caps out at 6 users. Headscale, Netbird, ZeroTier, and Twingate compared on real free-tier limits, self-hosting effort, and what switching actually costs.
Stay in the loop
Get the latest articles delivered to your inbox. No spam, unsubscribe anytime.
Riester Zulage Calculator: The Real Formula
Every Riester calculator online gives you a number with no formula behind it. Here's the actual Grundzulage + Kinderzulage + 4%-Eigenbeitrag math, worked by hand for a single earner and a two-child family.
Continue Reading