There are some instances that I have to use macvlan driver to place the container in a separate VLAN or zone within my network. Also, I have some containers that need to have its own IP address. I really didn’t have a use case where I need the host to access the container that was using macvlan until today. To paint a picture, see Figure 1.
Unfortunately, using the macvlan to give a container a static IP address would not allow the host to reach the container running a macvlan driver. This is also true from the container to the host. In my case, I am running the adguardhome container on 10.0.20.10 and my host is on 10.0.20.11. When I tried to update the host, I couldn’t because I am using the adguardhome container as my DNS server. To make it worse, my setup is one docker-compose.yml per service as shown in Figure 2. This post is basically how I got around with the problem with macvlan while keeping my IP scheme.
When deploying macvlan driver, it would not allow the host and container to reach each other even though they are on the same subnet. To get around this issue we need to create a route between the host and the container(s). Also, if you have multiple containers that need to be using macvlan, you can’t specifiy the macvlan in the docker-compose.yml file. The network need to be created manually, so lets address this one first.
Create a macvlan network
To create a network for macvlan, do the following. Adjust the value that applies to your setup.
docker network create --driver macvlan --subnet 10.0.20.0/24 --gateway 10.0.20.1 -o parent=ens18 dmz_net
Now that we have a network for macvlan with the name dmz_net. We can now reference this to our docker-compose file as shown in an example below.
version: "3" services: adguardhome: ... ...omitted for brevity... ... networks: dmz_net: ipv4_address: 10.0.20.100 networks: dmz_net: external: true
At this point, my AdGuard Home container is now reachable via the IP address of 10.0.20.100. Repeat the same config to the other containers if necessary.
Allowing routing between the host and macvlan containers
To get the host and macvlan containers to reach each other. We need to create a bridge and a static routes on the host. There are two ways to configure the needed route(s) either via network-manager or iproute2. I am running Debian and installed network-manager, but it should be the same with other distro.
Here is the IP scheme setup for this example:
- bridge – 10.0.20.2
- Host – 10.0.20.11
- AdGuard Home – 10.0.20.100
- Nextcloud – 10.0.20.101
- dmz_net – is a name of the link
Here is the thing with iproute2. Using the commands below will allow routing; however, it will not persistent. Meaning, if the host reboots, the iproute2 routing config will get deleted.
ip link add dmz_net link eth0 type macvlan mode bridge ip addr add 10.0.20.2/32 dev dmz_net ip link set dmz_net up ip route add 10.0.20.100/32 dev dmz_net ip route add 10.0.20.101/26 dev dmz_net
To make the iproute2 config permanent is to add it to the /etc/network/interfaces file as shown below
iface ens18 inet static address 10.0.20.11 netmask 255.255.255.0 gateway 10.0.20.1 post-up ip link add dmz_net link eth0 type macvlan mode bridge post-up ip addr add 10.0.20.2/32 dev dmz_net post-up ip link set dmz_net up post-up ip route add 10.0.20.100/32 dev dmz_net post-up ip route add 10.0.20.101/26 dev dmz_net
If you are using network-manager, it is a bit easier and it is a permanent configuration.
nmcli connection add con-name macvlan-ens18 type macvlan ifname macvlan-ens18 ipv4.addresses 10.0.20.2/24 dev ens18 mode bridge nmcli connection modify macvlan-ens18 ipv4.method manual nmcli connection modify macvlan-ens18 +ipv4.routes "10.0.20.100/32" nmcli connection modify macvlan-ens18 +ipv4.routes "10.0.20.101/32" nmcli connection up macvlan-ens18
At this point, my host is able to use AdGuard Home as its DNS server.