Macvlan network driver
Some applications, especially legacy applications or applications which monitor
network traffic, expect to be directly connected to the physical network. In
this type of situation, you can use the macvlan network driver to assign a MAC
address to each container's virtual network interface, making it appear to be
a physical network interface directly connected to the physical network. In this
case, you need to designate a physical interface on your Docker host to use for
the Macvlan, as well as the subnet and gateway of the network. You can even
isolate your Macvlan networks using different physical network interfaces.
Platform support and requirements
- The macvlan driver only works on Linux hosts. It is not supported on Docker Desktop for Mac or Windows, or Docker Engine on Windows.
- Most cloud providers block macvlan networking. You may need physical access to your networking equipment.
- Requires at least Linux kernel version 3.9 (version 4.0 or later is recommended).
- The macvlan driver is not supported in rootless mode.
Considerations
You may unintentionally degrade your network due to IP address exhaustion or to "VLAN spread", a situation that occurs when you have an inappropriately large number of unique MAC addresses in your network.
Your networking equipment needs to be able to handle "promiscuous mode", where one physical interface can be assigned multiple MAC addresses.
If your application can work using a bridge (on a single Docker host) or overlay (to communicate across multiple Docker hosts), these solutions may be better in the long term.
Containers attached to a macvlan network cannot communicate with the host directly, this is a restriction in the Linux kernel. If you need communication between the host and the containers, you can connect the containers to a bridge network as well as the macvlan. It is also possible to create a macvlan interface on the host with the same parent interface, and assign it an IP address in the Docker network's subnet.
Options
The following table describes the driver-specific options that you can pass to
--opt when creating a network using the macvlan driver.
| Option | Default | Description |
|---|---|---|
macvlan_mode | bridge | Sets the Macvlan mode. Can be one of: bridge, vepa, passthru, private |
parent | Specifies the parent interface to use. |
Create a Macvlan network
When you create a Macvlan network, it can either be in bridge mode or 802.1Q trunk bridge mode.
In bridge mode, Macvlan traffic goes through a physical device on the host.
In 802.1Q trunk bridge mode, traffic goes through an 802.1Q sub-interface which Docker creates on the fly. This allows you to control routing and filtering at a more granular level.
Bridge mode
To create a macvlan network which bridges with a given physical network
interface, use --driver macvlan with the docker network create command. You
also need to specify the parent, which is the interface the traffic will
physically go through on the Docker host.
$ docker network create -d macvlan \
--subnet=172.16.86.0/24 \
--gateway=172.16.86.1 \
-o parent=eth0 pub_net
If you need to exclude IP addresses from being used in the macvlan network, such
as when a given IP address is already in use, use --aux-addresses:
$ 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
802.1Q trunk bridge mode
If you specify a parent interface name with a dot included, such as eth0.50,
Docker interprets that as a sub-interface of eth0 and creates the sub-interface
automatically.
$ docker network create -d macvlan \
--subnet=192.168.50.0/24 \
--gateway=192.168.50.1 \
-o parent=eth0.50 macvlan50
Use an IPvlan instead of Macvlan
An ipvlan network created with option -o ipvlan_mode=l2 is similar
to a macvlan network. The main difference is that the ipvlan driver
doesn't assign a MAC address to each container, the layer-2 network stack
is shared by devices in the ipvlan network. So, containers use the parent
interface's MAC address.
The network will see fewer MAC addresses, and the host's MAC address will be associated with the IP address of each container.
The choice of network type depends on your environment and requirements. There are some notes about the trade-offs in the Linux kernel documentation.
$ docker network create -d ipvlan \
--subnet=192.168.210.0/24 \
--gateway=192.168.210.254 \
-o ipvlan_mode=l2 -o parent=eth0 ipvlan210
Use IPv6
If you have
configured the Docker daemon to allow IPv6,
you can use dual-stack IPv4/IPv6 macvlan networks.
$ docker network create -d macvlan \
--subnet=192.168.216.0/24 --subnet=192.168.218.0/24 \
--gateway=192.168.216.1 --gateway=192.168.218.1 \
--subnet=2001:db8:abc8::/64 --gateway=2001:db8:abc8::10 \
-o parent=eth0.218 \
-o macvlan_mode=bridge macvlan216
Usage examples
This section provides hands-on examples for working with macvlan networks, including bridge mode and 802.1Q trunk bridge mode.
NoteThese examples assume your ethernet interface is
eth0. If your device has a different name, use that instead.
Bridge mode example
In bridge mode, your traffic flows through eth0 and Docker routes traffic to
your container using its MAC address. To network devices on your network, your
container appears to be physically attached to the network.
Create a macvlan network called
my-macvlan-net. Modify thesubnet,gateway, andparentvalues to match your environment:$ docker network create -d macvlan \ --subnet=172.16.86.0/24 \ --gateway=172.16.86.1 \ -o parent=eth0 \ my-macvlan-netVerify the network was created:
$ docker network ls $ docker network inspect my-macvlan-netStart an
alpinecontainer and attach it to themy-macvlan-netnetwork. The-ditflags start the container in the background. The--rmflag removes the container when it stops:$ docker run --rm -dit \ --network my-macvlan-net \ --name my-macvlan-alpine \ alpine:latest \ ashInspect the container and notice the
MacAddresskey within theNetworkssection:$ docker container inspect my-macvlan-alpineLook for output similar to:
"Networks": { "my-macvlan-net": { "Gateway": "172.16.86.1", "IPAddress": "172.16.86.2", "IPPrefixLen": 24, "MacAddress": "02:42:ac:10:56:02", ... } }Check how the container sees its own network interfaces:
$ docker exec my-macvlan-alpine ip addr show eth0 9: eth0@tunl0: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP link/ether 02:42:ac:10:56:02 brd ff:ff:ff:ff:ff:ff inet 172.16.86.2/24 brd 172.16.86.255 scope global eth0 valid_lft forever preferred_lft foreverCheck the routing table:
$ docker exec my-macvlan-alpine ip route default via 172.16.86.1 dev eth0 172.16.86.0/24 dev eth0 scope link src 172.16.86.2Stop the container (Docker removes it automatically) and remove the network:
$ docker container stop my-macvlan-alpine $ docker network rm my-macvlan-net
802.1Q trunked bridge mode example
In 802.1Q trunk bridge mode, your traffic flows through a sub-interface of
eth0 (called eth0.10) and Docker routes traffic to your container using its
MAC address. To network devices on your network, your container appears to be
physically attached to the network.
Create a macvlan network called
my-8021q-macvlan-net. Modify thesubnet,gateway, andparentvalues to match your environment:$ docker network create -d macvlan \ --subnet=172.16.86.0/24 \ --gateway=172.16.86.1 \ -o parent=eth0.10 \ my-8021q-macvlan-netVerify the network was created and has parent
eth0.10. You can useip addr showon the Docker host to verify that the interfaceeth0.10exists:$ docker network ls $ docker network inspect my-8021q-macvlan-netStart an
alpinecontainer and attach it to themy-8021q-macvlan-netnetwork:$ docker run --rm -itd \ --network my-8021q-macvlan-net \ --name my-second-macvlan-alpine \ alpine:latest \ ashInspect the container and notice the
MacAddresskey:$ docker container inspect my-second-macvlan-alpineLook for the
Networkssection with the MAC address.Check how the container sees its own network interfaces:
$ docker exec my-second-macvlan-alpine ip addr show eth0 11: eth0@if10: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP link/ether 02:42:ac:10:56:02 brd ff:ff:ff:ff:ff:ff inet 172.16.86.2/24 brd 172.16.86.255 scope global eth0 valid_lft forever preferred_lft foreverCheck the routing table:
$ docker exec my-second-macvlan-alpine ip route default via 172.16.86.1 dev eth0 172.16.86.0/24 dev eth0 scope link src 172.16.86.2Stop the container and remove the network:
$ docker container stop my-second-macvlan-alpine $ docker network rm my-8021q-macvlan-net