Macvlan Networking

Imagine you are migrating a 15-year-old monolithic application to Docker. This legacy application is deeply tied to your physical network infrastructure. It uses hardcoded IP addresses for licensing servers, relies on Layer 2 broadcast discovery protocols to find database instances, and expects to be sitting directly on the same subnet as your office router and physical printers. It flat-out rejects Network Address Translation (NAT) and refuses to work behind a standard Docker Bridge.

You need a way to run this application in a container, but make the rest of the network believe it’s just another physical server plugged into the main switch.

Enter Macvlan.

1. The Virtual Sub-Interface

Macvlan is a network driver that allows you to assign a true physical MAC address directly to a container’s virtual network interface. From the perspective of your office router, your switches, and other devices on the subnet, the container appears as a completely independent physical device on the network. The Docker host effectively acts as a transparent switch, forwarding traffic directly to the container based on its assigned MAC address, bypassing the host’s IP stack and NAT entirely.

1. The Virtual Sub-Interface

Macvlan allows you to assign a MAC address to a container, making it appear as a physical device on your network. The Docker host acts like a switch, forwarding traffic directly to the container based on MAC address.

First Principles: Promiscuous Mode

To make this work, the host’s physical interface (e.g., eth0) must be configured to support multiple MAC addresses or be placed in promiscuous mode. Under normal circumstances, a network interface card (NIC) will drop any incoming packets that don’t match its own MAC address. Because the Docker host is now receiving packets destined for the container’s different MAC address, the NIC must be told to accept packets destined for MAC addresses other than its own.

[!NOTE] Cloud Provider Limitations: Many public cloud providers (like AWS, GCP, and Azure) block promiscuous mode and MAC address spoofing at the virtual switch level for security reasons. Macvlan is typically used in on-premises bare-metal environments or homelabs, not in public clouds (where you would use VPC routing instead).

2. Interactive: Macvlan vs Bridge

See the difference in how the router sees your container.

Router (Gateway)
Router's ARP Table
192.168.1.50 → AA:BB:CC:DD:EE:01 (Host)
192.168.1.51 → ??
Docker Host (192.168.1.50)
Container
IP: 172.17.0.2
Bridge Mode: The router ONLY sees the Host's MAC address. Traffic to the container is NAT'd. The container is hidden behind the host.

3. Configuration

To use Macvlan, you must bind it to a physical interface.

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

# Run container with a specific IP
docker run --net=pub_net --ip=192.168.1.51 -it alpine sh

[!CAUTION] Host Connectivity: By default, the host cannot ping a container on its own macvlan network due to security features in the Linux kernel. You need to create a secondary macvlan interface on the host to bridge this gap.

4. Summary

  • L2 Access: Containers appear as physical devices, maintaining compatibility with legacy apps that require direct subnet access or broadcast protocols.
  • Performance: Very high (no NAT or bridging overhead), as traffic is routed directly at the MAC layer.
  • Complexity: Requires promiscuous mode and careful IP management to prevent IP conflicts on the physical network.
  • Pitfalls: Requires an explicit bridge network setup if the host needs to communicate with its own macvlan containers. Cloud providers generally block this setup entirely.