How to setup and use a Docker MacVLAN network on a Synology

1 juillet 2021

I was searching a solution to expose services like Pi-hole or AdGuard directly on my network. Macvlan'ed was the solution to have a unique IP, but also to be routable from the NAS.

Description of the MacVLAN

Macvlan, MACVLAN or MAC-VLAN allows you to configure multiple Layer 2 (i.e. Ethernet MAC) addresses on a single physical interface. Macvlan allows you to configure sub-interfaces (also termed slave devices) of a parent, physical Ethernet interface (also termed upper device), each with its own unique (randomly generated) MAC address, and consequently its own IP address. Applications, VMs and containers can then bind to a specific sub-interface to connect directly to the physical network, using their own MAC and IP address.

Host Networking

SSH to your Syno Nas and run the following command:

$ ip link show

This displays all the IP links on your NAS. If, like me, you’ve made changes and tweaks over the years and forgotten all about them, you’ll see interfaces and configurations that will spark memories of happier times. Here’s the current output below:

(1) loopback
(2) sit0 for ipv6 — ipv4 tunneling
(3–6) physical NICs
(7–15) Virtual switch LAN ports
35, 51, 85 docker, macvlan and a vpn connection

What’s important here, is that when you create a macvlan switch, you need to understand *which* physical adapter to connect it to. For example if you run

$ ip link add macvlan0 link eth0 type macvlan mode bridge

This can fail. Why? Probably because you have Synology Virtual Machine manager installed, and within *its* networking configuration, you have Virtual Network 0 attached to eth0 for example.

⟹ with Synology Virtual Machine your interfaces became ovs_ethX

If you have any networking bonding on your physical NICs, this will show up as bond-system, bond0, etc. and again, when you try to create a Docker macvlan, it will fail unless you connect it to the right interface.

⟹ with network bonding your interfaces became bond-system, bond0, etc

And finally, with a combination of the two, you can also finish with something like ovs_bond0 !

How to setup MacVLAN network

Creating the MacVLAN on the host

This little script was made to create your MacVLAN network on the host

#!/bin/bash

# Set timeout to wait host network is up and running

sleep 60

# Host macvlan bridge recreate

ip link add macvlan-br0 link bond0 type macvlan mode bridge
ip addr add 192.168.0.209/32 dev macvlan-br0
ip link set dev macvlan-br0 address 22:cd:fc:ee:eb:6f
ip link set macvlan-br0 up
ip route add 192.168.0.208/28 dev macvlan-br0

So there, you need to adapt the parent interface (here bond0) and your network subnet, finally change the route.

In the beginning of the script, a pause is added to use it as a scheduled task in the Synology :

Run it as root at the boot-up of the Synology to restore your parameters on each restart.

Creating the MacVLAN network for Docker

Now, we need to inform docker of the new network we made available. This is a unique operation :

docker network create -d macvlan \
--subnet=192.168.0.0/24 \
--gateway=192.168.0.3 \
--ip-range=192.168.0.208/28 \
--aux-address 'host=192.168.0.101' \
-o parent=ovs_bond0 macvlan-br0

This network need to reflect the previous settings used to create the MacVLAN before, so please adapt these settings with what you set previously on your system.

Use MacVLAN in a Docker compose

Finally, this is a little example how to use the new network in a docker-compose, here to start a AdGuard

version: '2'

services:
  adguard:
    container_name: AdGuard 
    domainname: domain.io
    hostname: adguard
    image: adguard/adguardhome:latest
    mac_address: d0:ca:ab:cd:ef:02
    cap_add:
      - NET_ADMIN
    networks:
      default:
        ipv4_address: 192.168.0.210
    dns:
      - 127.0.0.1
      - 9.9.9.9
    ports:
      - 53/tcp
      - 53/udp
      - 443/tcp
      - 784/udp
      - 853/tcp
      - 3000/tcp
      - 5443/tcp
      - 5443/udp
    restart: unless-stopped
    volumes:
      - /volume1/docker/adguard/work:/opt/adguardhome/work
      - /volume1/docker/adguard/conf:/opt/adguardhome/conf
      - /volume1/docker/adguard/certs:/opt/adguardhome/certs:ro
    environment:
      - ServerIP=192.168.0.210
      - PROXY_LOCATION=adguard
      - VIRTUAL_HOST=adguard.domain.io
      - LETSENCRYPT_HOST=adguard.domain.io
      - VIRTUAL_PORT=80
      - TZ=Europe/Brussels
networks: default: external: name: macvlan-br0

Start it and your brand-new AdGuard is running on 192.168.0.210, last step is to put this IP as DNS server in your dhcp leases. The interesting parts is the network's one, you can reuse this for any service like an Unifi-Controller.



maggie
aux-address
Written by maggie on 12 février 2023
Hi, how comes the IP 192.168.0.101 for aux-address? Thanks for the great article.
Admin Admin
Written by Admin on 20 avril 2023
Hello, for me the aux-address is corresponding to my Bond 1 (main interface) host IP.
Mavyre
`ovs_bond0` is a garbage
Written by Mavyre on 12 septembre 2022
I'm using VMM plus a bond interface at the same time. I managed to create the Docker network and run containers without issues on it. However, they can't communicate as I lack a bridged macvlan switch. Unfortunately, when I try to create it using `ip link add mac0 ovs_bond0 type macvlan mode bridge`, I get the following error: Error: either `dev` is duplicate, or `ovs_bond0` is a garbage. Am I missing something? I can't find any solutions online.
bart
invalid argument
Written by bart on 27 avril 2022
Hello, When I try to run the script I get a invalid argument message. Can you help me out what I am doing wrong here tnx Bart
Admin Admin
Written by Admin on 1 juillet 2022
Could you please post the full error message to see what is wrong ?