By default, Docker containers sit on an isolated bridge network
(172.17.x.x). You reach them through port mappings like
-p 8080:80. This works for web dashboards, but it breaks for
anything that needs to be a first-class network citizen.
Services that need their own LAN IP:
- Pi-hole — network-wide DNS. Your router needs to reach it on port 53, and you can’t map port 53 through Docker without breaking the host’s own DNS resolution.
- Home Assistant / ESPHome — mDNS discovery for IoT devices. Broadcasts don’t cross Docker bridges.
- Plex / Jellyfin DLNA — UPnP discovery requires being on the same broadcast domain.
- Print servers, AirPlay receivers, SNMP collectors — any service that relies on broadcast/multicast.
MACVLAN and IPVLAN are Docker network drivers that solve this by giving containers their own presence on your physical LAN — their own IP, their own MAC (or shared MAC with IPVLAN), directly addressable from any device on your network.
This post covers how to set up both, when to use each, the crucial pitfalls to avoid, and real Compose examples for common services.
MACVLAN — The Default Choice
MACVLAN assigns each container a unique virtual NIC with its own MAC address. Your router sees the container as a separate physical device. DHCP assigns it an IP, or you set one statically.
How It Works
The Docker host’s physical interface (e.g., eth0) acts as a trunk.
The kernel creates virtual child interfaces, one per container, each
with its own MAC. The switch sees multiple MACs on one port — which
is perfectly normal for any switch made in the last 20 years.
Creating a MACVLAN Network
|
|
Breakdown of the flags:
--subnet— Your LAN subnet. Must match your physical network.--gateway— Your router’s IP.--ip-range— A subset Docker can assign from. Use a range outside your DHCP pool to avoid conflicts. If your router hands out 10.0.0.100–10.0.0.239, use 10.0.0.240/28 (240–254).-o parent— The host’s physical interface. Runip linkto find yours (eth0,enp3s0,ens18, etc.).
Running a Container on MACVLAN
|
|
With Docker Compose:
|
|
That’s it. Your Pi-hole is now at 10.0.0.53, directly accessible
from any device on your LAN. Set your router’s DNS to that IP.
Multiple Containers on the Same MACVLAN
You can attach many containers to the same MACVLAN network, each with a different IP:
|
|
The Host-to-Container Problem (Important!)
MACVLAN has a fundamental limitation: the Docker host cannot
communicate with its own MACVLAN containers. Your host at
10.0.0.10 cannot reach 10.0.0.53 — they’re on the same physical
interface, but MACVLAN’s internal routing prevents it.
This means:
docker execand health checks still work (they use the internal container namespace), butcurl http://10.0.0.53from the host fails.- If Pi-hole is your DNS server, the host itself can’t use it.
- Services running on the host can’t reach MACVLAN containers by their LAN IP.
The Fix: A Host-Side MACVLAN Bridge
Create a secondary MACVLAN interface on the host that bridges the gap:
|
|
Now 10.0.0.239 is the host’s MACVLAN IP, and it can reach all
containers in the 10.0.0.240/28 range. Traffic routes through
macvlan-bridge directly — it never leaves the host.
Persisting the Bridge (systemd)
Create a systemd unit so this survives reboots:
|
|
|
|
IPVLAN — When MACVLAN Won’t Work
IPVLAN is similar to MACVLAN but shares the host’s MAC address across all containers. The router sees one MAC with multiple IPs.
IPVLAN L2 Mode
Functionally similar to MACVLAN — containers get LAN IPs, traffic bridges at layer 2. The key difference is the shared MAC, which matters when:
- Your hosting provider or network restricts multiple MACs per port (common on VPS/VDS).
- You have many containers and want to avoid MAC table exhaustion on your switch (rare, but possible with hundreds of containers).
- Your Proxmox bridge drops MACVLAN traffic (see below).
Creation:
|
|
In Compose:
|
|
The host-to-container problem exists here too. The fix is the same approach — an IPVLAN host interface — but IPVLAN only supports L2 mode for host-side interfaces:
|
|
IPVLAN L3 Mode — Routed Networking
L3 mode puts containers in a completely separate subnet. The host routes between the container subnet and your LAN.
|
|
The gateway 10.10.0.1 is actually the host itself. You need to:
- Set up routing on the host (NAT or routing rules) so containers can reach the LAN.
- Add a static route on your LAN router pointing to the Docker host
for the
10.10.0.0/24subnet.
L3 mode eliminates broadcast noise entirely — no ARP, no DHCP broadcasts from containers. This is useful in security-segmented networks or when you want to isolate container traffic at layer 3. For most homelabs, stick with L2.
Proxmox Gotcha: Enable MAC Spoofing
If Docker is running inside a Proxmox VM, the Proxmox bridge
(vmbr0) drops traffic from unknown MAC addresses by default.
Fix: Enable MAC spoofing on the VM’s virtual NIC.
|
|
Alternatively, in the Proxmox UI: select the VM → Hardware → Network Device → Edit → check MAC spoofing.
Without this, MACVLAN traffic is silently dropped — containers get IPs but can’t communicate. IPVLAN avoids this issue because it shares the VM’s assigned MAC address.
MACVLAN + Regular Bridge Together
Many services benefit from having both a MACVLAN interface (for LAN access) and the default Docker bridge (for container-to-container communication):
|
|
Home Assistant is reachable at 10.0.0.100 from your LAN for IoT
device discovery, while other containers on docker-bridge can
reach it by the hostname homeassistant.
Troubleshooting
Container has an IP but can’t reach the internet
Probable cause: the --gateway IP is wrong, or the parent
interface is wrong. Verify:
|
|
Container can’t reach the internet via IPv6
MACVLAN supports IPv6, but you need to specify the subnet:
|
|
Some routers (especially MikroTik with IPv6 firewall rules) may require the container’s DUID or MAC to be registered.
“Network macvlan-home is not manually connectable” on docker compose up
If you used the short Compose syntax (network: instead of
networks:) or forgot external: true:
|
|
Pre-create the network with docker network create first.
Containers can reach LAN but not each other
MACVLAN containers can talk to each other directly if they’re on the same MACVLAN network. If they can’t, check your switch’s port isolation or private VLAN settings.
If using different MACVLAN networks with different parents or subnets, they need a router (your gateway) to communicate.
MACVLAN vs IPVLAN — Which Should You Use?
| Factor | MACVLAN | IPVLAN L2 | IPVLAN L3 |
|---|---|---|---|
| MAC per container | Unique | Shared | Shared |
| Switch MAC table | 1 entry per container | 1 entry total | 1 entry total |
| Host-to-container | Broken, needs bridge | Broken, needs bridge | Works (host is router) |
| Proxmox VM | Needs MAC spoofing | Works as-is | Works as-is |
| Broadcast handling | Passes through | Passes through | Isolated |
| Performance | Slight overhead per packet | Lower overhead | Lower overhead |
| Best for | Services needing unique identity | When you can’t add more MACs | Security isolation |
My recommendation for a homelab: Start with MACVLAN. It’s the most straightforward and works well for 1–20 containers. Switch to IPVLAN L2 only if you hit MAC limits or Proxmox issues. Use IPVLAN L3 when you want to completely container-isolate a subnet.
Complete Example: Pi-hole + Home Assistant + Scrypted
Here’s a full working setup with host bridge for DNS:
|
|
And the host-side bridge systemd unit (from the section above) so the Docker host itself gets DNS from Pi-hole.
Summary
MACVLAN and IPVLAN turn your Docker containers from isolated bridge guests into full LAN citizens. Setup takes five minutes:
- Create the network with
docker network create - Attach containers with static IPs
- Add the host-side bridge so the host can reach them (for MACVLAN)
- Enable MAC spoofing if running on Proxmox
The result is services that behave like physical devices — no port mapping, no NAT, just clean direct addressing. Pi-hole for network DNS, Home Assistant for mDNS device discovery, Plex for DLNA — all with their own IP, just like a Raspberry Pi on the network.
For most homelab scenarios, MACVLAN is the right choice. Keep IPVLAN in your back pocket for environments with MAC restrictions or Proxmox VMs that can’t enable spoofing.