Expanding a docker macvlan network

I’ve previously written about using macvlan networks with docker, this has proved to be a great way to make containers more like lightweight VMs as you can assign a unique IP on your network to them. Unfortunately when I did this I only allocated 4 IPs to the network, and 1 of those is used to provide a communication path from the host to the macvlan network.

Here is how I’ve used up those 4 IPs:

  1. wireguard – allows clients on wireguard to see other docker services on the host
  2. mqtt broker – used to bridge between my IoT network and the lan network without exposing all of my lan to the IoT network
  3. nginx – a local only webserver, useful for fronting Home Assistant and other web based apps I use
  4. shim – IP allocated to supporting routing from the host to the macvlan network.

If I had known how useful giving a container a unique IP on the network was, I would have allocated more up front. Unfortunately you can’t easily grow a docker network, you need to delete and recreate it.

As an overview here is what we need to do.

  • Stop any docker container that is attached to the macvlan network
  • Undo the shim routing
  • Delete the docker network
  • Recreate the docker network (expanded)
  • Redo the shim routing
  • Recreate the existing containers

This ends up not being too hard, and the only slightly non-obvious step is undoing the shim routing, which is the reverse of the setup.

The remainder of this post is a walk through of setting up a 4 IP network, then tearing it down and setting up a larger 8 IP network.

The first thing we’ll do is inspect the existing docker macvlan network. That will give us information on what we provisioned originally

There is quite a bit of output, but the chunk we care about is the “Config” section

This aligns with what we setup previously. However, if we pretend for a second we are starting on a brand new machine here are the docker macvlan setup steps we would do.

Cool, so that’s a 4 IP macvlan network setup. We can test it out with a new docker container

Now from the host – we can via the shim also see the new container

At this point we have a functioning 4 IP macvlan network. Time to tear it down and recreate it with more IPs. If we were to repeat the docker network inspect we would see the same information we had above.

Stop the docker container(s) running on it. If you don’t, you will not be able to remove the docker network.

Now we undo the shim routing

If we don’t do this, we won’t be able to re-do the shim setup because the old configuration will be present

Now we can remove the network, and re-create it. We will also redo the shim work.

This is almost identical to what we did for the 4 IP network, but we’ve expanded the IP range, and changed the aux-address to be the last IP in the range. For the shim, similarly we’ve specified a different IP and range.

While it might seem like we can just restart the containers, we actually need to recreate them. Why? Well, the docker containers aren’t bound to a network name, but the instance ID of the network. With this delete / re-create we’ve used the same names – but have new unique IDs. If we try to restart the old containers we will get errors that the network is missing.

Note: The shim-routing instructions are not persistent, so you’ll want to capture those into a shell script. Mine lives in /usr/local/bin/macvlansetup and is triggered with a cron @reboot entry.

Messing with my macvlan network setup seemed pretty scary. While I was doing this I even made a few mistakes, forgetting initially to undo the shim so I had to go back an fix that. I also discovered that restarting my containers didn’t work because of the network ID changing. In all cases I had reasonable error messages to guide me forward. This blog post is the perfect version of what I did, without my errors but notes on what to look out for. That’s it – now I’ve got 4 additional IPs to play with.

2 thoughts on “Expanding a docker macvlan network”

  1. Great post! Thank you. I’ve been wondering why so many guides suggest setting up a separate bridge network so that a container can interact with the host. Doesn’t this basically make everything work? Are there security issues to consider when creating a much larger macvlan network, perhaps with every IP address from 192.168.1.192 to 192.168.1.254, and having the shim post back to it?

    docker network create -d macvlan -o parent=enp3s0 \
    --subnet 192.168.1.0/24 \
    --gateway 192.168.1.1 \
    --ip-range 192.168.1.192/26 \
    --aux-address 'host=192.168.1.192' \
    myNewNet

    sudo ip link add myNewNet-shim link enp3s0 type macvlan mode bridge
    sudo ip addr add 192.168.1.192/32 dev myNewNet-shim
    sudo ip link set myNewNet-shim up
    sudo ip route add 192.168.1.192/26 dev myNewNet-shim

  2. Glad the post helped.

    You comment “doesn’t this make everything work?” – for me, it is magic. I’m able to use a container bound to one of the macvlan network IPs like it is a stand alone machine on my network.

    As for security concerns. This is all within my local network. I have the same security concerns I would have with any machine on my network.

Leave a Reply

Your email address will not be published. Required fields are marked *