Today, containers are everywhere from large scale production networks down to small home labs. In docker networking, two of the more advanced options for connecting containers to external networks are the macvlan
and ipvlan
drivers (docker VLANs). These drivers allow containers to directly connect to a network, almost as if they were separate physical devices. While they’re powerful tools, understanding when to use macvlan
or ipvlan
can be a bit confusing – especially since ipvlan
has both Layer 2 (L2) and Layer 3 (L3) modes, offering different ways to handle IPs and routing.
This guide dives into the key differences between macvlan
and ipvlan
, including how they manage MAC addresses, isolate broadcasts, and configure routes. You’ll also find step-by-step tutorials on setting up each driver in a real-world scenario with a Docker host and a VLAN subnet. The goal is to make sure these Docker containers are reachable by other devices on the host’s network and also have access to the host’s network resources.
By the end of this article, you’ll be able to choose the best vlan network driver for your needs – whether you’re running a home lab or a production environment. Additionally, I’ve included a troubleshooting section you might want to consult if you’re having trouble with docker’s vlan drivers.
In the past I’ve already written a shorter article on how to configure a docker macvlan
.
Contents
- 1 Wait, Layer what?
- 2 Overview of docker’s macvlan and ipvlan Drivers
- 3 Key Differences Between macvlan and ipvlan
- 4 Detailed tutorials
- 5 Troubleshooting
- 5.1 All: Is IP Forwarding Enabled?
- 5.2 All: Are Your Subnet Settings Right?
- 5.3 All: Is the Gateway Address Right?
- 5.4 macvlan: Is Promiscuous Mode Enabled?
- 5.5 macvlan/ipvlan L2: Is the Shim Routing Configured Properly?
- 5.6 ipvlan L3: Is the router configured correctly?
- 5.7 ipvlan L3: Is the subnet correct?
- 6 Comparison Summary Table: Key Differences Between Macvlan and Ipvlan
- 7 Conclusion
Wait, Layer what?
In computer networks, Layer 2 (L2) and Layer 3 (L3) refer to specific layers in the OSI model, which organizes network functions into seven distinct layers. L2, the data link layer, is responsible for direct data transfer between devices on the same local network. It uses MAC (Media Access Control, basically the “physical” address of your network adapter) addresses to identify devices and works within a single broadcast domain. Think of an L2 network as a local network or VLAN where every device can connect as if they’re on the same physical switch—no need for routing.
Layer 3 (L3), on the other hand, is where routing happens. L3 networks use IP addresses to direct data between different networks or subnets, allowing traffic to travel beyond a single local network. Routers operating at L3 handle things like IP addressing and subnetting, ensuring data finds its way across complex networks. This setup is key for managing communication between distinct network segments, giving you more control over traffic flow and security.
We don’t really care about the other layers of the stack in this article, I’ve only included them for context.
Overview of docker’s macvlan
and ipvlan
Drivers
In docker, L2 and L3 come into play through the macvlan
and ipvlan
drivers, which most people in the beginning are not aware of. When setting up Docker networks, most people start with the default NAT setup, which works fine for many things. But sometimes, you want containers to act as if they’re fully part of the host’s network. Say, you’re deploying multiple containers that run webUIs on port 80.
You could now start juggling ports around. At a certain point I start to get lost in port numbers. This is where Docker’s macvlan
and ipvlan
drivers come in. The macvlan
driver operates at L2, giving each container its own MAC address and allowing it to act like an independent device on the host’s network.
While both drivers help achieve to make containers look like independent devices on the host’s network, macvlan
and ipvlan
have their own quirks and strengths. The trick is knowing when to use each and how they work differently – especially since ipvlan
supports both L2 and L3 modes, giving it added flexibility.
macvlan
Overview
The macvlan
driver’s idea is creating separate MAC addresses for each container, making them look like individual devices on the network. Think of it as cloning the host’s network interface and giving each container its own unique MAC address. This setup works really well for situations where containers need to communicate with other devices directly, as if they were plugged into the same switch.
One thing to keep in mind, though, is that macvlan
isolates containers from the host itself, meaning they can’t communicate directly with the host’s main interface unless you add extra routing. The tutorial part will also show you how to get host communication back again in a minute or so. But if your goal is to have containers interact with other devices on the network, macvlan
is the go-to choice. It’s especially handy in environments that need each container to have its own MAC address, like older networks that rely on MAC-based filtering.
Advantages and Limitations of macvlan
Advantages:
- Each container has its own MAC address, making them easily identifiable on the network.
- Containers communicate directly with other devices on the same network, great for L2 setups.
- Ideal for setups that need individual MAC addresses or MAC-based filtering.
Limitations:
- Containers can’t talk directly to the host without additional setup.
- Some network setups might struggle with a lot of MAC addresses, which could limit scalability.
ipvlan
Overview
The ipvlan
driver is a bit different and, in some ways, more flexible. It offers two modes:
- Layer 2 mode
- Layer 3 mode
In L2 mode, ipvlan
is like macvlan
but skips the unique MAC addresses. Instead, all containers share the same MAC address as the host, using IP aliases instead. This can be really helpful in larger networks where managing tons of MAC addresses could become a headache. That’s usually not the case in home networks, but worth noting at this point.
Then there’s L3 mode, which is where ipvlan
really stands out. In L3 mode, each docker network gets its own subnet and relies on IP-based routing to connect with external networks. Rather than handling communication at the MAC level, L3 mode manages traffic at the IP level, making it perfect for setups that need a bit more control over traffic flow and network segmentation. It does require some extra routing configuration, though, so it’s best suited for scenarios where you’re comfortable setting up IP routes. To use L3 mode of the ipvlan driver you should definitely have some experience using iptables. Again, in both L2 and L3 mode of the ipvlan driver, container-host communication has to be set up separately.
Advantages and Limitations of ipvlan
Advantages:
- L2 mode reduces MAC address management, keeping things simpler on networks with MAC constraints.
- L3 mode allows for IP-based isolation, ideal for controlling traffic and network segments.
- Works well in setups that don’t require each container to have a unique MAC address.
Limitations:
- Containers can’t communicate directly with the host due to the
ipvlan
isolation design. - L3 mode can be a bit more complex to set up since it requires configuring IP routing.
Key Differences Between macvlan
and ipvlan
While both macvlan
and ipvlan
can connect containers to a host’s network, they do so in different ways. This impacts how containers communicate with each other, the host, and other devices on the network. We talked about the advantages and limitations of both drivers already. Now let’s look at the main differences, which will help clarify when to choose one over the other.
Network Layers (L2 vs. L3)
The core difference between macvlan
and ipvlan
is the network layer they operate on. macvlan
is an L2 network driver, meaning it assigns each container its own unique MAC address. This allows the container to act like a separate device at the data link layer, which is why macvlan
is ideal for simple, local network communication.
ipvlan
, on the other hand, can operate at either L2 or L3, so it’s a bit more versatile. In L2 mode, it behaves similarly to macvlan
, but without assigning unique MAC addresses to each container. In L3 mode, ipvlan
operates at the IP (so, Layer 3 of the OSI model) level rather than the MAC(Layer 2) level, meaning traffic is routed based on IPs rather than MAC addresses. This L3 approach offers more options for network segmentation and traffic control, but also requires setting up IP routing, which can be a whole other can of worms.
MAC Address Assignment
macvlan
assigns each container its own MAC address, so it’s perfect for environments that need each device to have a unique (hardware) identity on the network. This is the case for example for networks with MAC-based filtering or setups that expect a unique MAC for each device. A more common service that needs individual MAC addresses for identification is DHCP. Other examples of common services that need individual MAC addresses to function correctly include wake-on-LAN, discovery services like Bonjour, some IoT devices or security cameras.
In contrast, ipvlan
shares the host’s MAC address across all containers. This reduces MAC address complexity, which can be an advantage on networks with MAC address limits. Or, if you simply don’t care if the container has an individual MAC address and your routing doesn’t require it. However, this also means containers are not distinguishable at the MAC level, which may not be ideal if unique MACs are needed for network management. If your containers have static IPs and also don’t use DHCP you usually do not need this for networks at home.
Broadcast and Network Isolation
Because macvlan
works at L2, containers can send and receive broadcast traffic. This can be useful when containers need to discover each other on the network, such as with certain services that rely on broadcast communication. As mentioned earlier, Bonjour or DHCP do rely on this. However, macvlan
also isolates containers from the host network by default, so they can’t directly access the host interface without extra routing (which is quite easy and we’ll get into later).
ipvlan
is a bit different here: in both L2 and L3 modes, it inherently isolates container traffic from the host interface. L2 mode allows for some broadcast communication within the ipvlan
network, but L3 mode doesn’t handle broadcasts at all—traffic between containers relies solely on IP routing. This makes L3 mode useful for setups where you want strict control over which networks can interact in which way.
Routing and Gateway Configuration
Routing configuration is another key difference. macvlan
typically requires minimal routing setup for simple L2 communication, since each container has a unique MAC address on the network. Again, if you want containers to communicate directly with the host, you’ll need to add specific routes. It’s very simple and needs to be done once only.
With ipvlan
in L3 mode, more complex routing is often needed. It’s also only a one time things, but here you should know what you’re doing, because the effort is a bit higher and usually there isn’t much of a “one size fits all” solution to this. Each container is on its own subnet, so IP routes must be configured to ensure that traffic can flow between these subnets and the main network. This makes ipvlan
L3 mode ideal for setups that need traffic segmentation but also requires a bit more network know-how.
When to use which driver?
So, when should you use which driver now? I think the choice is basically boils down to a few question. I’ve made a small cheat sheet. If you want the PDF, I’ll put a link at the end of the article.
Let’s quickly go through the decision tree.
Access to the host’s network necessary?
There might be cases where you don’t even need access to the host’s network from inside the container. Or cases where the NAT docker provides per default is enough. This likely isn’t the case for you when you’re reading this 😊 But still, sometimes it’s overlooked so I kept it in here.
Is L2 communication needed?
Essentially, do you have any service(s) inside the container that rely on having a unique MAC Layer 2 identity? Unless you’re running a DHCP server or network discovery services inside your containers, this should not be the case. But, maybe you simply cannot to put your network interface into promiscuous mode? This definitely is a requirement for the macvlan
driver.
Are there L2 limitations?
There may be scenarios where you only have a limited amount of MAC addresses available for your network or you cannot have a network device in promiscuous mode. In these settings ipvlan
L3 is your goto choice, since everything is handled on L3 without any requirements for L2.
Detailed tutorials
For all of the following tutorials, we assume the following setting (where it applies):
- Debian 12 or later based distribution
- Network:
192.168.178.0/24
- Gateway’s IP:
192.168.178.1
- Docker host’s IP:
192.168.178.10
- Container subnet:
192.168.178.16/28
- Container subnet for
ipvlan
L3:192.168.177.0/24
- Shim’s IP:
192.168.178.15
- Host interface device name is
enp0s3
This should be a pretty typical home or small office network setup. The containers will be put into the subnet 192.168.178.16/28
(which covers the IP range .16
through .31
). That should be enough for most setups. The “Shim” will have the IP ending in .15
. The “Shim” is the network bridge that will the container-host communication. This means that the IPs .11
through .14
can be used for VMs or other things if you want and you still have everything in a neat IP address block. Make sure to adapt these settings to your scenario if necessary. Most if not everything will work for distributions other than debian 12 or newer, too.
As long as the network configuration is ifup
/ifdown
based, everything here should work for you. Let’s look at how we set up the prerequisites for the vlan drivers.
For all tutorials, make sure that you have IP forwarding enabled
sysctl -w net.ipv4.ip_forward=1
You need to enable this after every reboot. For testing that surely is ok. But for a production system we want this to be on permanently. To make this permanent on debian based distributions follow these steps:
- Open the file
/etc/sysctl.conf
and find the following (usually commented) line:
#net.ipv4.ip_forward=1
- Uncomment (remove the preceeding #) the line
- Save the changes and reload the services
sysctl -p /etc/sysctl.conf1
/etc/init.d/procps restart
Setup Tutorial: macvlan
Configuration
This setup will allow containers to appear as separate devices on the network, each with its own MAC address and IP, so they can communicate directly with other network devices.
Preparations
In order for a network card to listen to multiple MAC addresses, you need to enable promiscuous mode for this interface. Check if promiscuous mode is on with the ip
command:
ip -d link
This will output something similar to the image below. In this case the interface enp0s3 has promiscuity 1
, which means it already is in promiscuous mode.
In case it says promiscuity 0, enable it by calling
ip link set enp0s3 promisc on
This is not permanent yet, you’d need to enable it after each reboot. We’ll make it permanent later.
Docker macvlan
Network Creation
With macvlan
, we’ll create a new network interface for each container that connects it directly to the host’s network. Let’s set up this macvlan
network in Docker:
docker network create -d macvlan \
--subnet=192.168.178.0/24 \
--ip-range=192.168.178.16/28 \
--gateway=192.168.178.1 \
-o parent=enp0s3 \
macvlan_net
Explanation:
-d macvlan
: Specifies the driver asmacvlan
.--subnet=192.168.178.0/24
: Assigns themacvlan
network the specified subnet within the main network.--ip-range=192.168.178.16/28
: IP address range docker’s DHCP will supply to the containers.--gateway=192.168.178.1
: Sets the network gateway, typically your router.-o parent=enp0s3
: Links themacvlan
network to the host’s physical network interface.
Container Creation and IP Assignment in macvlan
Now we can launch containers that use the new macvlan
network. Each container will be assigned an IP within the .16 - .31
range, which allows them to be addressed individually on the main network.
To launch a container with a specific IP on the macvlan_net
network run the following command:
docker run -it --rm --network macvlan_net --ip 192.168.178.16 alpine sh
This command starts an Alpine container with the IP 192.168.178.1
6. You can substitute the IP .1
6 with any available IP in the .16 - .31
range. If you leave it empty, docker’s DHCP server will supply a IP within the range specified during network creation to the container.
Testing Network Connectivity with macvlan
After setting up the macvlan
network and starting containers, let’s test connectivity to confirm that they can communicate with the host’s network and other devices.
- Router and Other Network Devices: From within the container, try pinging the router (
192.168.178.1
) to confirm external network connectivity:
ping 192.168.178.1
- Host: Try to ping the host (
192.168.178.10
) from the contiainer. By default,macvlan
isolates containers from the host. So this should fail! To allow containers to reach the host directly, additional routing usually is necessary (see “Optional: Enable host access” below). - Test Container-to-Container Communication: Launch another container with an IP in the
.16 - .31
range, let them ping eachother.
Optional: Enable host access
Since macvlan
isolates containers from the host, they can’t directly access the host’s IP (192.168.178.10
) by default. Here’s a workaround to enable host-to-container communication:
Create a macvlan
bridge interface on the Host: Add a new macvlan
interface on the host. Make sure that the new interface has an IP in the same subnet as the containers.
ip link add macvlan-shim link enp0s3 type macvlan mode bridge
ip addr add 192.168.178.15/32 dev macvlan-shim
ip link set macvlan-shim up
ip route add 192.168.178.16/28 dev macvlan-shim
You should now be able to ping the host (192.168.178.10
).
Making the changes permanent
For the macvlan
driver to permanently function properly, we need to permanently enable three things in the system:
- Promiscuous mode
- Bridge interface
- IP routing between host and container subnet
Promiscuous mode: Debian per default uses ifupdown
for network configuration. So your existing network interfaces should already be inside /etc/network/interfaces
. To permanently enable promiscuous mode, just append the post-up and pre-down (optional) commands.
auto enp0s3
iface enp0s3 inet static
address 192.168.178.10
netmask 255.255.255.0
gateway 192.168.178.1
post-up ip link set enp0s3 promisc on
pre-down ip link set enp0s3 promisc off
This will enable promiscuous mode after starting the interface and disable it before shutting the interface down. Make sure to adapt to your setting.
Bridge interface and routing: These two settings go hand in hand, thus I’ve put them here together. To add the network bridge after every reboot and have the traffic from the host to the containers routed through this interface, add the following to your /etc/network/interfaces
:
auto macvlan-shim
iface macvlan-shim inet static
pre-up ip link add macvlan-shim link enp0s3 type macvlan mode bridge
address 192.168.178.15
netmask 255.255.255.240
post-up ip route add 192.168.178.16/28 dev macvlan-shim
pre-down ip route del 192.168.178.16/28 dev macvlan-shim
post-down ip link del macvlan-shim
With these settings in place, everything needed for the macvlan driver should be restored from the next reboot.
Setup Tutorial: ipvlan
Configuration (L2 Mode)
Again, make sure that you’ve enabled IP forwarding, otherwise the ipvlan
driver will not work.
Docker ipvlan
Network Creation (L2 Mode)
Now, let’s create an ipvlan
network in docker. The ipvlan
L2 mode shares the host’s MAC address. We’ll set up the network to assign IPs from the 192.168.178.16/28
subnet.
docker network create -d ipvlan \
--subnet=192.168.178.0/24 \
--gateway=192.168.178.1 \
-o parent=enp0s3 \
-o ipvlan_mode=l2 \
ipvlan_l2_net
Explanation:
-d ipvlan
: Specifies the driver asipvlan
.--subnet=192.168.178.0/2
4: Assigns the main network as subnet for theipvlan
network.--gateway=192.168.178.1
: Sets the gateway to the router.-o parent=enp0s
3: Links theipvlan
network to the host’s main interface.-o ipvlan_mode=l2
: Configures theipvlan
network in L2 mode.
From what I know, you cannot restrict the IP address range docker’s DHCP server supplies to the containers when you’re using the ipvlan
driver. You have to manually make sure that you do not supply IP addresses to the containers that are already used in the host network.
Container Creation and IP Assignment in ipvlan
L2 Mode
With the ipvlan
network set up, you can launch containers on this network. To avoid IP address conflicts, each container will be assigned an IP from the .16 - .31
range within the subnet manually.
Example: Launch a container with a specific IP on the ipvlan_l2_net
network.
docker run -it --rm --network ipvlan_l2_net --ip 192.168.178.16 alpine sh
This command starts an Alpine container with the IP 192.168.178.16
. If you’re trying all tutorials in this article and already followed the macvlan
tutorial, make sure the IP is available or use a different one. You can assign other IPs within the .16 - .31
range as needed.
Testing Network Connectivity with ipvlan
L2 Mode
Now that the container is set up, it’s time to test its connectivity to confirm it can reach devices on the host’s network.
- Router and Other Network Devices: From within the container, test connectivity to the router at
192.168.178.1
and other devices on the host’s network:
ping 192.168.178.1
- Host: Try to ping the host (
192.168.178.10
) from the contiainer. By default,ipvlan
isolates containers from the host. So this will most likely fail! To allow containers to reach the host directly, additional routing usually is necessary (see “Optional: Enable host access” below).
- Test Container-to-Container Communication: Start another container on
ipvlan_l2_net
with a different IP (e.g.,192.168.178.17
), and verify that they can communicate by pinging between the containers.
Optional: Enable Host Access
Again, if you need the containers to communicate directly with the host, you need to add a bridge interface on the host.
Create an macvlan
bridge interface on the Host: Add a new macvlan
interface on the host. Make sure that the new interface has an IP in the same subnet as the containers.
ip link add macvlan0 link enp0s3 type macvlan mode bridge
ip addr add 192.168.178.16/28 dev macvlan-shim
ip link set macvlan-shim up
ip route add 192.168.178.16/28 dev macvlan-shim
You should now be able to ping the host (192.168.178.10
)
Making the Changes Permanent
If you don’t need host access when using the ipvlan
driver in L2 mode, you can just skip this part. If you need host access, the only settings that needs to be restored after a reboot is the bridge interface and the routing rules. To make these settings permanent, open /etc/network/interfaces
and add these lines to the end:
auto macvlan-shim
iface macvlan-shim inet static
pre-up ip link add macvlan-shim link enp0s3 type macvlan mode bridge
address 192.168.178.15
netmask 255.255.255.240
post-up ip route add 192.168.178.16/28 dev macvlan-shim
pre-down ip route del 192.168.178.16/28 dev macvlan-shim
post-down ip link del macvlan-shim
Setup Tutorial: ipvlan
Configuration (L3 Mode)
In ipvlan
L3 mode, docker creates a virtual, isolated IP network where containers are assigned IP addresses from the specified subnet. External networks are connected through IP routing. As mentioned earlier, Unlike L2 mode, ipvlan
L3 mode doesn’t support broadcast or direct MAC communication.
Because the ipvlan
l3 subnet must not overlap with the host’s network, in this setup we’ll configure the 192.168.1.0/24
subnet for containers, which will communicate with the main 192.168.178.0/24
network through IP routing.
Again, make sure you’ve got IP forwarding enabled on the docker host.
Host Network Setup for L3 Mode
In order for devices on the main network (192.168.178.0/24
) to reach containers in the 192.168.1.0/24
subnet, you’ll need to add a route on your network’s main router. In Germany these are often AVM FRITZ!Boxes, for which you’ll find easy instructions in their documentation. If you’ve got a different brand router, just search the web for something like “<Manufacturer> <Model> add static ip route“. This will direct traffic intended for the container subnet through the docker host.
On the Router: Add a static route with the following details:
- Destination:
192.168.177.0/24
- Gateway:
192.168.178.10
(the docker host’s IP)
Docker ipvlan
Network Creation (L3 Mode)
Let’s create an ipvlan
network in L3 mode within the specified subnet. This isolates containers on their own IP network, routing traffic through IP addresses rather than relying on MAC addresses.
docker network create -d ipvlan \
--subnet=192.168.177.0/24 \
--gateway=192.168.178.10 \
-o parent=enp0s3 \
-o ipvlan_mode=l3 \
ipvlan_l3_nte
Routing Configuration for Containers in L3 Mode
As mentioned earlier, the docker host also acts as router and gateway for the L3 subnet that the containers will be put in. The docker host is already aware of the ipvlan
L3 subnet, so no extra setup is needed here.
Container Creation and IP Assignment in ipvlan
L3 Mode
Now that we have the ipvlan
L3 network set up, let’s launch containers and assign them IP addresses within the 192.168.177.0/24
subnet.
Example: Start a container with a specific IP on the ipvlan_l3_net
network.
docker run -it --rm --network ipvlan_l3_net --ip 192.168.177.2 alpine sh
This command launches an Alpine container with IP 192.168.177.2
. Again, you can assign other IPs in the 192.168.177.0/24
subnet as needed.
Testing Network Connectivity with ipvlan
L3 Mode
With routing configured and a test container in place, we can now verify that containers can communicate with the main network and beyond.
- Ping the Router and External Devices: From within a container, try pinging the router at
192.168.178.1
and other devices on the main network to confirm outgoing connectivity:
ping 192.168.178.1
- Test Container-to-Host and Host-to-Container Communication: By default,
ipvlan
isolates the host from containers, but with the routing setup, you should be able to ping containers from the host and vice versa. From the host:
ping 192.168.177.2
- Containers and External Devices: From another device on the
192.168.178.0/24
network, try pinging a container’s IP (e.g.,192.168.177.2
) to ensure full network reachability.
ping 192.168.177.2
Also try pinging devices on your host’s network from your container to test full network reachability.
Troubleshooting
The different docker vlan drivers prove to be very reliable once in place. But, on your way there, you might get stuck one of the other way. I’ve dockumented some common pitfalls on when configuring docker’s vlan drivers.
All: Is IP Forwarding Enabled?
One system setting that is often overlooked is IP forwarding. Any of docker’s vlan drivers will not function properly, if IP forwarding isn’t enabled. To enable IP forwarding, run the following command as root:
sysctl -w net.ipv4.ip_forward=1
With the steps below you can permanently enable IP forwarding on debian based systems:
- Open the file
/etc/sysctl.conf
and find the following (usually commented) line:
#net.ipv4.ip_forward=1
- Uncomment (remove the preceeding #) the line
- Save the changes and reload the services
sysctl -p /etc/sysctl.conf1
/etc/init.d/procps restart
All: Are Your Subnet Settings Right?
Most of the errors in this category should be caught by docker itself already when creating the network or the corresponding container. But still, there might be a possibility that your subet settings are not right. For the very simple scenario we’ve looked at here it should be hard to mess up. But with more complicated setups?
Try to verify you subnets with a subnet calculator.
All: Is the Gateway Address Right?
For all drivers you must apply the correct gateway address to the docker network you create. Additionally, routing must be configured properly on this gateway.
macvlan
& ipvlan
L2: The gateway typically s your network’s router. In our examples this is 192.168.178.1
. Double check if this is set as gateway for your docker network. You can inspect an existing network’s configuration using the inspect option (see below).
ipvlan
L3: For ipvlan
L3, the configured gateway address for an ipvlan L3 network must be the docker host’s IP address, in our examples here 192.168.178.10. Us docker’s network inspection command to verify your ipvlan
L3 network’s gateway address.
docker network inspect NETWORK
There are a few options you can use for this command, documented in docker’s docs.
macvlan
: Is Promiscuous Mode Enabled?
For the macvlan
driver to function properly, the network interface it uses must be in promiscuous mode. Check if promiscuous mode is on with the ip
command:
ip -d link
This will output something similar to the image below. In this case the interface enp0s3 has promiscuity 1
, which means it already is in promiscious mode.
In case it says promiscuity 0, enable it by calling
ip link set enp0s3 promisc on
To make this permanent, run the following commands on systems based on debian 12 or later:
To permanently enable promiscuous mode for an interface, open the file /etc/network/interfaces and add the last two lines to the settings of the interface.
auto enp0s3
iface enp0s3 inet static
address 192.168.178.10
netmask 255.255.255.0
gateway 192.168.178.1
post-up ip link set enp0s3 promisc on
pre-down ip link set enp0s3 promisc off
macvlan
/ipvlan
L2: Is the Shim Routing Configured Properly?
Wmat I’m calling “Shim” here is the bridge interface that allows host access. If this is incorrectly set up, the communication between the docker host and the containers may be impaired. One thing to double check is if the subnet the bridge interface is routing to is correct:
ip route show dev macvlan-shim
Make sure to replace the device you’re looking at (the dev macvlan-shim
part) with your bridge. Details are in the macvlan tutorial section. The device should only be routing traffic for the container subnet, 192.168.178.16/28
in the tutorials in this post. To add the route, use the ip command:
ip route add 192.168.178.16/28 dev macvlan-shim
ipvlan
L3: Is the router configured correctly?
For the devices on the docker host’s network to be able to connect to the containers in your ipvlan
L3 network, your host network’s router must know how to reach the subnet of your ipvlan
. Make sure to configure your docker host as gateway for this subnet, in our case 192.168.178.10
. This varies depending on your network’s router, so I can’t give you specific instructions here.
ipvlan
L3: Is the subnet correct?
Since the docker ipvlan
L3 networks cannot overlap your host’s network, the subnet usually is different. Make sure the two networks do not overlap and check if the ipvlan
L3’s subnet is set to the one you intended. In the examples above we used 192.168.177.0/24
as subnet for the ipvlan
L3 network. To check the configuration of your docker subnet, use the docker network inspect command.
docker network inspect NETWORK
There are a few options you can use for this command, documented in docker’s docs.
Comparison Summary Table: Key Differences Between Macvlan and Ipvlan
While macvlan
and ipvlan
drivers both allow Docker containers to connect directly to a network without NAT, they handle communication and network configuration in different ways. Here’s a summary of their key differences:
Feature | macvlan | ipvlan (L2) | ipvlan (L3) |
---|---|---|---|
MAC Address Handling | Unique per container | Shared with host | Shared with host |
Broadcast Support | Yes | Yes | No |
Host Isolation | Yes (by default) | Yes (by default) | Yes (by default) |
Routing Complexity | Minimal | Minimal | High |
Best Use Case | Unique MAC or legacy networks | MAC simplification | IP isolation and segmentation |
Conclusion
Choosing between Docker’s macvlan
and ipvlan
drivers really depends on your specific networking needs. Feel free to use the decision tree from this article. If your containers need to be treated as distinct devices on the network with unique MAC addresses, macvlan
is the way to go. It’s simple to configure for most Layer 2 setups and works well in environments that rely on MAC-based network policies or discovery protocols like mDNS and ARP.
On the other hand, ipvlan
offers more flexibility, particularly with its support for both L2 and L3 modes. It’s a solid choice for scenarios where you want to avoid managing individual MAC addresses or need to isolate container traffic using IP routing. The L3 mode, in particular, shines in environments that require traffic segmentation or advanced routing between subnets.
Whether you’re managing a home lab, a small office setup, or a production environment, understanding these drivers will help you tailor docker networking to your specific requirements. With the detailed tutorials provided, you should now have the tools to configure macvlan
and ipvlan
networks effectively and make the most of docker’s advanced networking capabilities.
Here’s all cheat sheets from this article, plus the PDF for you to download:
If you have questions or comments, I’d love to hear them. Use the comments below or the contact form to drop me a line!