| |

Docker 34 🐳 Macvlan and IPvlan Networks: Exposing Containers directly to Physical LAN Subnets

A bridge network puts the container behind a NAT. The container has its own IP, but it is on a virtual subnet, and the outside world reaches it only through published ports. Some applications do not accept this. A legacy application that uses broadcast discovery, a monitoring tool that needs to see all traffic, a device that must have a specific IP on the LAN—these expect to be directly connected to the physical network. The macvlan and ipvlan drivers provide this. They assign the container an IP from the physical subnet and, in the macvlan case, a unique MAC address. The container appears on the LAN as a separate device .

Key point: The macvlan driver gives each container its own MAC address and IP on the physical subnet. The ipvlan driver gives the container its own IP but shares the host interface’s MAC. Both make the container reachable from the LAN without NAT or port mapping. The trade-off is that the host cannot communicate with the container through the parent interface. This is a Linux kernel restriction, and the workaround is a macvlan interface on the host itself .


Why macvlan and ipvlan exist

The LAN presence problem. A container on a bridge network is behind NAT. The outside world sees the host’s IP, not the container’s. An application that relies on Layer 2 broadcast, multicast, or ARP cannot work behind a NAT . The macvlan and ipvlan drivers remove the NAT. The container is on the physical subnet, and the LAN sees it as a peer.

The legacy problem. A legacy application that was written for a physical server expects to run on a physical network. It may bind to a specific interface, use raw sockets, or rely on DHCP. Migrating it to a container on a bridge network requires changes. The macvlan driver makes the container’s network environment identical to a physical machine’s, and the legacy application runs without modification .

The MAC exhaustion problem. The macvlan driver assigns a unique MAC address to each container. The network equipment must handle promiscuous mode, and a large number of unique MAC addresses can cause “VLAN spread,” where the switch’s CAM table fills and the network degrades . The ipvlan driver solves this: the containers share the host interface’s MAC address and each has its own IP. The switch sees one MAC, and the MAC exhaustion is avoided .

The Wi-Fi problem. Many Wi-Fi access points drop frames from MAC addresses they do not recognize. The macvlan driver assigns new MAC addresses, so the containers’ traffic is dropped. The ipvlan driver shares the host’s MAC, so the traffic is accepted. On Wi-Fi, ipvlan works and macvlan often does not .

The L3 routing problem. The ipvlan driver has an L3 mode. In L3 mode, the container’s IP is on a different subnet from the host, and the host acts as a router. Broadcast and multicast are filtered. The L3 mode is for routed container networking, where the container’s subnet is not the physical LAN’s subnet .


a. The macvlan driver: unique MAC, unique IP

The macvlan driver creates a network where each container has its own MAC address and IP on the physical subnet. The parent interface is the physical interface the traffic goes through.

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

The --subnet and --gateway are the physical network’s subnet and gateway. The -o parent=eth0 specifies the host interface that the macvlan network attaches to. The gateway is the external router, not a Docker proxy .

A container is started on the network with a specific IP.

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

The container has the IP 192.168.1.50 and its own MAC address. Other machines on the LAN can reach it directly. The curl http://192.168.1.50 from another host on the LAN works .

The macvlan driver has a mode option. The default is bridge, which is the mode described above. Other modes include vepa, passthru, and private, but bridge is the standard .

The --aux-address option excludes an IP from being assigned. This is useful when an IP is already in use by another device.

docker network create -d macvlan \
  --subnet=192.168.32.0/24 \
  --ip-range=192.168.32.128/25 \
  --gateway=192.168.32.254 \
  --aux-address="my-router=192.168.32.129" \
  -o parent=eth0 macnet32

The --ip-range limits the container IPs to a sub-range of the subnet. The --aux-address blacklists the specified IP .

The 802.1Q trunk mode uses a sub-interface as the parent. The parent name includes the VLAN tag.

docker network create -d macvlan \
  --subnet=192.168.50.0/24 \
  --gateway=192.168.50.1 \
  -o parent=eth0.50 macvlan50

The eth0.50 is a sub-interface of eth0 tagged with VLAN ID 50. Docker creates the sub-interface automatically .

The host cannot communicate with the macvlan containers through the parent interface. This is a Linux kernel restriction. The traffic is filtered for isolation. The workaround is to create a macvlan interface on the host itself, with the same parent, and assign it an IP in the network’s subnet .


b. The ipvlan driver: shared MAC, unique IP

The ipvlan driver is similar to macvlan but the containers share the parent interface’s MAC address. Each container still has its own IP .

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

The default mode is L2, which is the mode that is similar to macvlan. The container gets an IP on the physical subnet, and the switch sees the host’s MAC for both the host and the container .

The L3 mode is different. In L3 mode, the container’s IP is on a different subnet from the host. The host acts as a router, and the container’s IP is reachable only through the host.

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

In L3 mode, the default route is set to the parent interface because ARP, broadcast, and multicast are filtered. The parent interface’s IP and subnet must be different from the container network’s subnet. The L3 mode is for routed container networking .

The --internal flag isolates the containers from external communication. If the -o parent= option is omitted, Docker creates a dummy parent interface, and the result is the same as the --internal flag. The network is completely isolated .

docker network create -d ipvlan \
  --subnet=192.168.10.0/24 \
  isolated1

The ipvlan L2 mode works on Wi-Fi because the containers share the host’s MAC. The access point sees only one MAC address, the host’s, and the traffic is accepted .


c. The host communication limitation and the use cases

The macvlan and ipvlan drivers have a limitation: the host cannot communicate with the containers through the parent interface. The Linux kernel filters the traffic between the host’s default namespace and the macvlan/ipvlan containers for isolation. The host cannot ping the container, and the container cannot ping the host .

The workaround is to create a macvlan interface on the host itself. The host’s interface is a peer of the containers’ interfaces, and the host can communicate with the containers through it.

ip link add mac0 link eth0 type macvlan mode bridge
ip addr add 192.168.1.100/24 dev mac0
ip link set mac0 up

The host’s macvlan interface has an IP in the same subnet as the containers. The host can reach the containers, and the containers can reach the host through the macvlan interface .

The use cases for the two drivers:

Use CaseDriver
Legacy application expecting physical networkmacvlan
Network monitoring toolmacvlan
IoT device with a specific LAN IPmacvlan
Wi-Fi networkipvlan L2
Switch with MAC address limitsipvlan L2
Routed container networkingipvlan L3

The macvlan driver is the right choice when the container must appear as a distinct device on the LAN, with its own MAC address. The ipvlan driver is the right choice when the switch limits the MAC addresses, or when the network is Wi-Fi and the access point filters unknown MACs. The ipvlan L3 mode is for the cases where the container network is a separate subnet and the host routes the traffic .

Both drivers work only on Linux hosts. They are not supported on Docker Desktop for Mac or Windows, and they are not supported in rootless mode. The macvlan driver also requires the network equipment to handle promiscuous mode .


Complete Example Session

# ============================================
# PART 1: MACVLAN NETWORK
# ============================================
docker network create -d macvlan \
  --subnet=192.168.1.0/24 \
  --gateway=192.168.1.1 \
  -o parent=eth0 pub_net
# ============================================
# PART 2: CONTAINER WITH SPECIFIC IP
# ============================================
docker run -d --name web --network pub_net --ip=192.168.1.50 nginx
# ============================================
# PART 3: VERIFY FROM LAN
# ============================================
curl http://192.168.1.50
# ============================================
# PART 4: HOST CANNOT REACH CONTAINER
# ============================================
ping 192.168.1.50
# No response (kernel filters the traffic)
# ============================================
# PART 5: HOST MACVLAN WORKAROUND
# ============================================
ip link add mac0 link eth0 type macvlan mode bridge
ip addr add 192.168.1.100/24 dev mac0
ip link set mac0 up
ping 192.168.1.50
# ============================================
# PART 6: IPVLAN NETWORK (L2)
# ============================================
docker network create -d ipvlan \
  --subnet=192.168.1.0/24 \
  --gateway=192.168.1.1 \
  -o parent=eth0 ipv_net
# ============================================
# PART 7: IPVLAN CONTAINER
# ============================================
docker run -d --name web --network ipv_net --ip=192.168.1.51 nginx
# ============================================
# PART 8: IPVLAN L3 MODE
# ============================================
docker network create -d ipvlan \
  --subnet=10.10.0.0/24 \
  -o ipvlan_mode=l3 \
  -o parent=eth0 ipvl3net
# ============================================
# PART 9: AUX ADDRESS AND IP RANGE
# ============================================
docker network create -d macvlan \
  --subnet=192.168.32.0/24 \
  --ip-range=192.168.32.128/25 \
  --gateway=192.168.32.254 \
  --aux-address="my-router=192.168.32.129" \
  -o parent=eth0 macnet32
# ============================================
# PART 10: 802.1Q VLAN TRUNK
# ============================================
docker network create -d macvlan \
  --subnet=192.168.50.0/24 \
  --gateway=192.168.50.1 \
  -o parent=eth0.50 macvlan50

The ten parts covered the macvlan network, a container with a specific IP, the LAN verification, the host limitation, the host workaround, the ipvlan L2 network, an ipvlan container, the ipvlan L3 mode, the aux address and IP range, and the 802.1Q VLAN trunk.


Quick Reference

Macvlan vs IPvlan

AspectMacvlanIPvlan
MAC addressUnique per containerShares host’s MAC
IP addressUnique per containerUnique per container
Wi-Fi supportOften failsWorks
Switch MAC limitsCan exhaustNo issue
LAN visibilityDistinct deviceSame MAC as host
Modesbridge, vepa, passthru, privateL2, L3
Host communicationBlockedBlocked

Network Creation Options

OptionPurpose
--subnetPhysical subnet
--gatewayExternal gateway
-o parent=eth0Host interface
--ip-rangeContainer IP sub-range
--aux-addressExcluded IP
-o macvlan_mode=macvlan mode
-o ipvlan_mode=l2ipvlan L2 mode
-o ipvlan_mode=l3ipvlan L3 mode

Use Case Selection

ScenarioDriver
Legacy app on wired LANmacvlan
Network monitoringmacvlan
Wi-Fi environmentipvlan L2
MAC-limited switchipvlan L2
Routed container networkipvlan L3

Host Communication

DriverHost to Container
macvlanBlocked (kernel)
ipvlanBlocked (kernel)
WorkaroundHost macvlan interface

Best Practices

✅ Do This:

# Use macvlan for wired LAN presence
docker network create -d macvlan --subnet=... -o parent=eth0    # ✅

# Use ipvlan for Wi-Fi or MAC-limited switches
docker network create -d ipvlan -o parent=eth0                  # ✅

# Reserve a specific IP for the container
docker run --network pub_net --ip=192.168.1.50                  # ✅

# Use --aux-address to exclude used IPs
--aux-address="router=192.168.1.1"                              # ✅

# Create a host macvlan interface for host-container communication
ip link add mac0 link eth0 type macvlan mode bridge             # ✅

# Use 802.1Q sub-interface for VLAN isolation
-o parent=eth0.50                                               # ✅

# Use ipvlan L3 for routed container networking
-o ipvlan_mode=l3                                               # ✅

❌ Don’t Do This:

# Don't expect host-container communication by default
ping 192.168.1.50  # from host, fails                          # ⚠️

# Don't use macvlan on Wi-Fi
docker network create -d macvlan ...  # AP may drop frames     # ⚠️

# Don't forget the parent interface
docker network create -d macvlan --subnet=...  # no parent     # ❌

# Don't use macvlan on Docker Desktop
# Not supported on Mac or Windows                                # ❌

# Don't assign the host's IP to a container
--ip=192.168.1.10  # if that is the host's IP                  # ❌

# Don't use macvlan when a bridge would work
# Bridge is simpler and sufficient for most cases                # ⚠️

Common Pitfalls

PitfallWhy It HappensFix
Host cannot reach containerKernel restrictionCreate host macvlan interface
Container cannot reach hostKernel restrictionSame workaround
Wi-Fi failsAP drops unknown MACsUse ipvlan
Switch MAC exhaustionUnique MAC per containerUse ipvlan
IP conflictDHCP assigns same IPUse --aux-address
VLAN not workingParent is not taggedUse eth0.50 format
Docker Desktop failsNot supportedUse Linux host

Real-World Examples

1. Macvlan on Wired LAN

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

2. Container with Static IP

docker run -d --network pub_net --ip=192.168.1.50 nginx

3. IPvlan on Wi-Fi

docker network create -d ipvlan \
  --subnet=192.168.1.0/24 \
  -o parent=wlan0 ipv_net

4. IPvlan L3 Routed

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

5. Exclude IP

--aux-address="router=192.168.1.1"

6. IP Range

--ip-range=192.168.1.128/25

7. VLAN Trunk

-o parent=eth0.50

8. Host Workaround

ip link add mac0 link eth0 type macvlan mode bridge
ip addr add 192.168.1.100/24 dev mac0
ip link set mac0 up

9. Verify from LAN

curl http://192.168.1.50

10. Check Container IP

docker exec web ip addr show eth0

Visual

Macvlan Network

┌─────────────────────────────────────────────────────────────┐
│  PHYSICAL LAN (192.168.1.0/24)                              │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐          │
│  │  Host       │  │ Container A │  │ Container B │          │
│  │ 192.168.1.10│  │ 192.168.1.50│  │ 192.168.1.51│          │
│  │ MAC: aa:bb  │  │ MAC: cc:dd  │  │ MAC: ee:ff  │          │
│  └─────────────┘  └─────────────┘  └─────────────┘          │
│                                                             │
│  Each container has its own MAC and IP.                     │
│  The LAN sees them as distinct devices.                     │
│  The host cannot reach them through eth0.                   │
│                                                             │
└─────────────────────────────────────────────────────────────┘

IPvlan L2 Network

┌─────────────────────────────────────────────────────────────┐
│  PHYSICAL LAN (192.168.1.0/24)                              │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐          │
│  │  Host       │  │ Container A │  │ Container B │          │
│  │ 192.168.1.10│  │ 192.168.1.50│  │ 192.168.1.51│          │
│  │ MAC: aa:bb  │  │ MAC: aa:bb  │  │ MAC: aa:bb  │          │
│  └─────────────┘  └─────────────┘  └─────────────┘          │
│                                                             │
│  Containers share the host's MAC.                           │
│  The switch sees one MAC.                                   │
│  Works on Wi-Fi.                                            │
│                                                             │
└─────────────────────────────────────────────────────────────┘

IPvlan L3 Network

┌─────────────────────────────────────────────────────────────┐
│  HOST (192.168.1.10)                                        │
│  ┌─────────────────────────────────────────────────────┐    │
│  │  Container A (10.10.0.2)                            │    │
│  │  Container B (10.10.0.3)                            │    │
│  │                                                     │    │
│  │  The host routes between the subnets.               │    │
│  │  Broadcast and multicast are filtered.              │    │
│  └─────────────────────────────────────────────────────┘    │
│                                                             │
│  Routed container networking.                               │
│                                                             │
└─────────────────────────────────────────────────────────────┘

Host Communication Workaround

┌─────────────────────────────────────────────────────────────┐
│  WITHOUT WORKAROUND                                         │
│                                                             │
│  Host (eth0) ────X──── Container (macvlan)                  │
│  Kernel filters the traffic.                                │
│                                                             │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  WITH WORKAROUND                                            │
│                                                             │
│  Host (mac0) ────────▶ Container (macvlan)                  │
│  Host (eth0)                                            │
│                                                             │
│  The mac0 interface is a peer of the containers.            │
│                                                             │
└─────────────────────────────────────────────────────────────┘

Summary

ItemValue
MacvlanUnique MAC + IP per container
IPvlan L2Shared MAC, unique IP
IPvlan L3Routed container networking
Parent interface-o parent=eth0
Static IP--ip=192.168.1.50
IP range--ip-range=192.168.1.128/25
Exclude IP--aux-address="router=192.168.1.1"
VLAN trunk-o parent=eth0.50
Host limitationCannot reach containers
WorkaroundHost macvlan interface
PlatformLinux only

Key takeaways:

  • The macvlan driver gives each container its own MAC address and IP on the physical subnet. The container appears on the LAN as a distinct device. The switch must handle promiscuous mode, and a large number of MAC addresses can degrade the network .
  • The ipvlan driver shares the host’s MAC address. The containers have unique IPs but the switch sees one MAC. This avoids the MAC exhaustion problem and works on Wi-Fi, where access points may drop frames from unknown MACs .
  • The ipvlan L3 mode is for routed container networking. The container’s IP is on a different subnet, and the host acts as a router. Broadcast and multicast are filtered .
  • The host cannot communicate with the containers through the parent interface. This is a Linux kernel restriction for isolation. The workaround is to create a macvlan interface on the host itself, with an IP in the container network’s subnet .
  • The --aux-address option excludes an IP from being assigned. Use it when an IP is already in use by another device. The --ip-range limits the container IPs to a sub-range .
  • The 802.1Q trunk mode uses a sub-interface as the parent. The eth0.50 parent creates a sub-interface tagged with VLAN ID 50. Docker creates and deletes the sub-interface automatically .
  • These drivers work only on Linux hosts. They are not supported on Docker Desktop for Mac or Windows, and not in rootless mode .

Remember: The macvlan and ipvlan drivers are the tools for putting a container directly on the physical LAN. The macvlan gives the container its own MAC and IP; the ipvlan shares the MAC and gives the container its own IP. The choice between them is the choice of the MAC identity: unique MAC for the LAN presence, shared MAC for the Wi-Fi and MAC-limited switches. The host cannot reach the containers through the parent interface, and the workaround is a macvlan interface on the host. These are the drivers for the cases where the NAT is not acceptable and the container must be a first-class citizen of the physical network.



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!