Skip to content
Networking

Macvlan and IPvlan in Docker: When to Use Each

Macvlan gives containers unique MACs (each looks like a physical machine); IPvlan shares the host MAC. Real use cases (legacy apps, hardware licensing, multi-tenant), gotchas (host can't reach containers, AWS blocks them), and configuration recipes.

A
Abhishek Patel12 min read

Infrastructure engineer with 10+ years building production systems on AWS, GCP,…

Macvlan and IPvlan in Docker: When to Use Each
Macvlan and IPvlan in Docker: When to Use Each

The Quick Answer

Most Docker networks use bridge, host, overlay, or none. Macvlan and IPvlan are the rarer drivers for cases where containers need to look like physical devices on the LAN. Macvlan gives each container its own MAC address and IP — to other devices on the L2 network, it's indistinguishable from a physical machine. IPvlan shares the host's MAC but gives each container a unique IP, in either L2 mode (containers share broadcast domain) or L3 mode (host acts as a router). Picking between them comes down to: do you need each container to be a unique L2 endpoint (use macvlan), or do you need many IPs without consuming MAC table space (use IPvlan). Most teams reaching for either need them for legacy apps that hate NAT, hardware-pinned licensing, exotic monitoring, or multi-tenant L2 isolation.

For the more common drivers (bridge, host, overlay), see Docker networking. This article is the long-tail for when those don't fit.

What Each Driver Actually Does

Macvlan

Macvlan attaches a virtual network interface to the host's physical NIC, with its own MAC address and IP. From the network's perspective, each macvlan container is a distinct host on the L2 segment. Packets to/from the container don't pass through Docker's iptables or NAT rules — they go directly to the physical NIC.

# Create a macvlan network on eth0
docker network create -d macvlan \
  --subnet=192.168.1.0/24 \
  --gateway=192.168.1.1 \
  -o parent=eth0 \
  pub_net

# Run a container with a fixed IP
docker run -d --network pub_net --ip=192.168.1.100 --name web nginx

Other devices on 192.168.1.0/24 reach the container at 192.168.1.100 directly. ARP works as if the container were a physical machine.

IPvlan L2 Mode

Like macvlan, but containers share the host's single MAC address. Each container has a unique IP; the host's MAC table doesn't grow with container count.

docker network create -d ipvlan \
  --subnet=192.168.1.0/24 \
  --gateway=192.168.1.1 \
  -o parent=eth0 \
  -o ipvlan_mode=l2 \
  ipv_net

docker run -d --network ipv_net --ip=192.168.1.101 --name api nginx

IPvlan L3 Mode

Containers don't share an L2 broadcast domain at all. The host acts as a router; each container gets its own subnet that's routed by the host. ARP / broadcast traffic doesn't reach containers — useful for very large deployments where broadcast traffic would otherwise overwhelm the network.

docker network create -d ipvlan \
  --subnet=10.1.0.0/16 \
  -o parent=eth0 \
  -o ipvlan_mode=l3 \
  ipv3_net

Side-by-Side: When to Use Each

PropertyMacvlanIPvlan L2IPvlan L3
Each container has unique MAC?YesNo (shares host MAC)No
Each container has unique IP?YesYesYes (in subnet routed by host)
Containers participate in L2 broadcast?YesYesNo (L3 only)
Switch needs promiscuous mode?Yes (often)NoNo
Host can reach container by default?NoNoYes
MAC table impact on switchGrows with container countSingle MACSingle MAC
Best forEach container = network identityMany IPs, one MACRouted multi-tenant, no broadcasts

The Real Use Cases

Legacy Apps That Hate NAT

Some applications fundamentally don't work behind NAT — they advertise their own IP in the protocol, or they require strict L2 connectivity. Examples: certain VoIP servers (SIP signaling), some industrial IoT protocols (BACnet, EtherNet/IP), legacy financial-trading multicast feeds. Wrapping these in a bridge network with NAT often breaks them; macvlan or ipvlan L2 keeps them happy.

Hardware-Pinned Licensing

Some software licenses bind to a specific MAC address. If you containerize the app and put it behind NAT, the license tries to validate against the bridge IP/MAC and fails. Macvlan lets the container present a stable MAC that matches the licensed identity. (Pragmatically: license terms may forbid this; check legal before deploying.)

Multi-Tenant L2 Isolation

For multi-tenant deployments where each tenant should be a distinct L2 endpoint (think: a hosting provider where each tenant container gets its own routable IP visible to peers), macvlan provides cleaner isolation than bridge networks plus complex NAT rules.

Exotic Monitoring / SNMP Tools

Some legacy monitoring tools probe containers via L2 broadcast or expect distinct MACs in the ARP table. Macvlan satisfies these tools. Modern monitoring (Prometheus, OpenTelemetry) doesn't need this — but if you're integrating with a 1990s-era SNMP NMS, macvlan may be the path.

Container-Per-IP Without Bridge Overhead

For very high-throughput workloads where the bridge driver's iptables rules add measurable latency (typical: 50-200 µs per packet), macvlan and ipvlan bypass iptables entirely and shave that overhead. For latency-sensitive workloads at scale this can matter — though usually host networking is simpler.

The Gotchas Nobody Documents Until You Hit Them

1. Host-Container Communication Is Disabled by Default

The single most surprising behavior. With macvlan, the host kernel can NOT reach containers via the macvlan interface. ping 192.168.1.100 from the host fails even though every other device on the LAN can reach the container fine. This is a kernel limitation, not a Docker bug.

Workaround: Create a separate macvlan interface on the host that's bridged to the same network:

# Create a macvlan-shim interface on the host
ip link add macvlan-shim link eth0 type macvlan mode bridge
ip addr add 192.168.1.250/24 dev macvlan-shim
ip link set macvlan-shim up
ip route add 192.168.1.100/32 dev macvlan-shim

Now the host can reach the container at 192.168.1.100 via the shim interface. IPvlan L3 mode doesn't have this problem (the host is the router).

2. Switch-Side Promiscuous Mode for Macvlan

Switches often track MAC-to-port mappings to forward traffic efficiently (MAC learning). With macvlan, multiple MACs come from a single physical port (the host's NIC). Some switches treat this as a security violation (MAC flooding) and block traffic. The fix: enable promiscuous mode on the switch port, or use a switch feature like Cisco's "switchport port-security maximum N." On managed Wi-Fi networks (corporate APs), this often is impossible — APs typically don't allow multiple MACs per client.

3. Cloud Providers Often Block Macvlan

AWS, GCP, Azure VPCs strictly enforce MAC-to-IP bindings on virtual interfaces. Containers using macvlan to advertise their own MACs typically can't communicate at all on cloud VPCs — the SDN drops their packets as MAC spoofing. There are workarounds (some cloud providers allow disabling source/destination checks, AWS supports multiple secondary IPs per ENI which IPvlan can leverage), but these are case-by-case.

Practical: macvlan is overwhelmingly used on bare-metal Docker hosts, not on cloud VMs.

4. IPvlan L3 Requires Routing on the Network

IPvlan L3 mode treats the host as a router for container subnets. This means the upstream network (your switch / router / firewall) needs to know where to send packets for the container subnet — typically a static route to the host. On a tightly-controlled corporate network this is usually fine; on a flat residential network, it requires manual routing setup most users don't have permissions for.

5. DHCP Doesn't Work By Default

Macvlan and IPvlan containers don't run DHCP clients by default — they use static IPs assigned at docker run. Some Docker plugins (like ipvlan-dhcp) add DHCP support, but they're third-party. For simple deployments, just assign IPs from a predetermined pool tracked in your IPAM tool of choice.

Comparison with Overlay Networking

For multi-host Docker (Swarm / Kubernetes), overlay networking is the standard answer. Overlay encapsulates container traffic in VXLAN, transports it over the underlay network, and decapsulates at the destination. Pros: works on any underlay, handles cloud VPCs cleanly, no L2 dependencies. Cons: VXLAN encapsulation overhead (~50 bytes/packet), tunnel-setup complexity, harder to debug.

Macvlan and IPvlan don't replace overlay — they're for different use cases. Overlay is the right choice for cross-host container connectivity in cloud environments. Macvlan / IPvlan are for single-host deployments where containers need to participate in the host's physical L2 network. For Kubernetes-specific networking patterns see Kubernetes pods, deployments, and services.

Real Configuration Recipes

Recipe: Macvlan with Static IP Pool

# Carve out a sub-range of your LAN for containers
# Assume LAN is 192.168.1.0/24, gateway 192.168.1.1
# Reserve 192.168.1.128/26 for containers (62 usable IPs)

docker network create -d macvlan \
  --subnet=192.168.1.0/24 \
  --gateway=192.168.1.1 \
  --ip-range=192.168.1.128/26 \
  -o parent=eth0 \
  containers_net

# Run with auto-assigned IP from the range
docker run -d --network containers_net --name web nginx

# Or with explicit IP
docker run -d --network containers_net --ip=192.168.1.130 --name api nginx

Recipe: IPvlan L2 for IP-Heavy Deployments

docker network create -d ipvlan \
  --subnet=192.168.1.0/24 \
  --gateway=192.168.1.1 \
  --ip-range=192.168.1.128/25 \
  -o parent=eth0 \
  -o ipvlan_mode=l2 \
  many_ips_net

# Run 50+ containers each with their own IP, all sharing host MAC
for i in {1..50}; do
  docker run -d --network many_ips_net --name container_$i nginx
done

Recipe: IPvlan L3 for Multi-Tenant Routed Subnets

docker network create -d ipvlan \
  --subnet=10.1.0.0/24 \
  -o parent=eth0 \
  -o ipvlan_mode=l3 \
  tenant_a

docker network create -d ipvlan \
  --subnet=10.2.0.0/24 \
  -o parent=eth0 \
  -o ipvlan_mode=l3 \
  tenant_b

# On the upstream router/switch, add static routes:
# 10.1.0.0/24 via <host_ip>
# 10.2.0.0/24 via <host_ip>

docker run -d --network tenant_a --ip=10.1.0.5 --name app1 nginx
docker run -d --network tenant_b --ip=10.2.0.5 --name app2 nginx

Recipe: Macvlan with Host Communication Workaround

docker network create -d macvlan \
  --subnet=192.168.1.0/24 \
  --gateway=192.168.1.1 \
  -o parent=eth0 \
  pub_net

docker run -d --network pub_net --ip=192.168.1.100 --name web nginx

# Add macvlan-shim on host so host can reach container
sudo ip link add macvlan-shim link eth0 type macvlan mode bridge
sudo ip addr add 192.168.1.250/24 dev macvlan-shim
sudo ip link set macvlan-shim up
sudo ip route add 192.168.1.100/32 dev macvlan-shim

# Now host can reach 192.168.1.100
curl http://192.168.1.100

Decision Matrix

SituationPickWhy
App needs unique MAC (license, NAT-hating protocol)MacvlanEach container is a distinct L2 endpoint
Need many IPs but switch limits MAC countIPvlan L2Single MAC, multiple IPs
Multi-tenant routed subnets, no broadcast pollutionIPvlan L3Routed mode, no L2 broadcast domain
Running on AWS/GCP/Azure VMsBridge or overlay (NOT macvlan)Cloud SDNs typically block macvlan
Multi-host Docker Swarm clusterOverlayCross-host connectivity, cloud-friendly
Standard web app, single host, no special L2 needsBridgeThe default; works everywhere
App needs to bind to host network namespaceHost networkingBypasses Docker networking entirely

Watch out: If you find yourself reaching for macvlan or ipvlan, ask first whether the underlying problem (legacy app, license enforcement, monitoring tool) can be solved differently. These drivers add operational complexity for narrow benefit. Most "I need macvlan" turns out to be "I need to publish this port via host networking" or "I need to update the legacy app's NAT-handling logic."

Frequently Asked Questions

What's the difference between Macvlan and IPvlan in Docker?

Macvlan gives each container a unique MAC address — to the network, every container looks like a separate physical machine. IPvlan shares the host's MAC across all containers but gives each a unique IP. Macvlan is for "each container is a network identity"; IPvlan is for "many IPs without inflating the switch's MAC table."

Why can't my host reach Docker macvlan containers?

Linux kernel limitation — host kernel and macvlan child interfaces on the same parent NIC are firewalled from communicating. Workaround: create a separate macvlan-shim interface on the host bridged to the same network, give it an IP in the same subnet, and route container traffic through it. IPvlan L3 mode avoids this issue entirely (host is the router).

Does Macvlan work on AWS or GCP?

Generally no. AWS/GCP/Azure VPCs strictly enforce MAC-to-IP bindings on virtual NICs and drop packets that look like MAC spoofing — which macvlan's multiple MACs per host trigger. There are workarounds (multiple secondary IPs per ENI in AWS, IPvlan on cloud sometimes works), but for most cloud deployments use bridge or overlay networking instead.

When should I use IPvlan L3 mode?

For multi-tenant or large-scale deployments where you want the host to act as a router for container subnets, eliminating L2 broadcast traffic. The trade-off: the upstream network needs to know about routes to your container subnets (typically a static route on the router/switch). IPvlan L3 isolates tenants cleanly and scales to tens of thousands of containers without ARP/broadcast saturation.

Do I need a managed switch to use Macvlan?

Often yes. Macvlan generates multiple MACs from a single physical NIC port, which some switches block as MAC flooding. Managed switches let you enable promiscuous mode or raise the MAC-per-port limit. On unmanaged consumer switches, macvlan usually works — but on enterprise switches with strict port security, macvlan needs explicit allow rules. IPvlan avoids this entirely by using a single shared MAC.

Can I use Macvlan with Kubernetes?

Yes, via the Multus CNI plugin which lets pods have multiple network interfaces. Macvlan is a common choice for the secondary interface in Kubernetes telco / NFV deployments where each pod needs to be a distinct network endpoint. For typical Kubernetes apps, the standard pod network (Calico, Cilium) is the right answer; macvlan is for specialized use cases. See Kubernetes pods for the standard model.

Bottom Line

Macvlan and IPvlan are the rare-but-essential network drivers for cases where containers must look like physical L2 devices on the host's LAN. Macvlan when each container needs a unique MAC (legacy apps, hardware-pinned licensing, multi-tenant L2 isolation). IPvlan L2 when you need many IPs but want a single MAC. IPvlan L3 for routed multi-tenant deployments. Avoid both on cloud VMs (cloud SDNs block them). For the more common drivers (bridge, host, overlay) used in 99% of Docker deployments, see Docker networking.

A

Written by

Abhishek Patel

Infrastructure engineer with 10+ years building production systems on AWS, GCP, and bare metal. Writes practical guides on cloud architecture, containers, networking, and Linux for developers who want to understand how things actually work under the hood.

Related Articles

Enjoyed this article?

Get more like this in your inbox. No spam, unsubscribe anytime.

Comments

Loading comments...

Leave a comment

Stay in the loop

New articles delivered to your inbox. No spam.