Using docker with macvlan on Synology NAS
In the previous post, I investigated using Docker with the macvlan network driver, to allow containers to have unique external IP addresses. This is the follow-up post where I apply the changes to my Synology NAS.
Implementing (Synology)
The steps are basically the same as above, but the numbers are different (the Synology NAS is going to get
192.168.28.32/28; also eth0, rather than eno1):
sudo docker network create \
--driver macvlan \
--subnet 192.168.28.0/24 \
--gateway 192.168.28.1 \
--ip-range 192.168.28.32/28 \
--aux-address 'host=192.168.28.46' \
--opt parent=eth0 macvlan0
sudo ip link add macvlan0 link eth0 type macvlan mode bridge
sudo ip addr add 192.168.28.46/32 dev macvlan0
sudo ip link set macvlan0 up
sudo ip route add 192.168.28.32/28 dev macvlan0
Note that these settings are not persistent.
Creating macvlan0 at boot-up
To make them persistent, create a file (I called mine /volume1/docker/macvlan0-up.sh) and put the commands in it (we
don’t need sudo), like this:
#!/bin/sh
ip link add macvlan0 link eth0 type macvlan mode bridge
ip addr add 192.168.28.46/32 dev macvlan0
ip link set macvlan0 up
ip route add 192.168.28.32/28 dev macvlan0
Mark it as executable and then use Control Panel / Scheduled Tasks / Create / Triggered Task to run the script as root at Boot-up.
Testing
Basically the same as above; the HTML files go in /volume1/docker/nginx.
mkdir -p /volume1/docker/nginx/nginx-1 /volume1/docker/nginx/nginx-2
echo 'One' > /volume1/docker/nginx/nginx-1/index.html
echo 'Two' > /volume1/docker/nginx/nginx-2/index.html
sudo docker run --net=macvlan0 --ip=192.168.28.33 --detach --name nginx-1 -v "/volume1/docker/nginx/nginx-1:/usr/share/nginx/html" nginx:alpine
sudo docker run --net=macvlan0 --ip=192.168.28.34 --detach --name nginx-2 -v "/volume1/docker/nginx/nginx-2:/usr/share/nginx/html" nginx:alpine
And, again, browsing to http://192.168.28.33 or http://192.168.28.34, I see the expected One or Two responses.
Moreover, both of those are accessible from the Ubuntu container started on the Linux host above.
Conclusions
You can (relatively) easily run containers on a Synology NAS with locally-accessible IP addresses. This means that you can run multiple containers using the same port number, or where the NAS is also listening on that port.
Whether you need to is another question. Synology Web Station does rudimentary reverse-proxying, including to containers. It supports associating a different TLS certificate with each service, but the Let’s Encrypt integration is kinda lacking: no wildcards unless you’re using Synology’s DDNS, and it’s very manual.
What’s next?
- I’ve not made the settings persist over a restart. I’ll fix that tomorrow (and update this page). If you’re feeling
impatient, the links above have you covered.
- Something made the link (specifically the route) vanish even without a restart. I’m not sure what, yet.
- It would be nice if we didn’t have to use IP addresses, so I need to do something with DNS.
- This will involve some kind of messing around with the router. Currently, adding host entries requires manual steps and restarting things.
- I solved that already for the K3s cluster, so I’m thinking that running CoreDNS inside a container on the NAS would work. I found a docker plugin for it. If that doesn’t work, I already wrote https://github.com/rlipscombe/dockerns.
- TLS and certificates. I need to look at Let’s Encrypt.
- Actually installing Forgejo.
Follow-ups
- Instead of running multiple instances of
nginxwith different web roots, it’s easier to use thetraefik/whoamiimage. - It’s not necessary to specify
--ip=when starting the container; Docker will just use the next available address from the configured address range.- Once the addresses have run out, you’ll get
Error response from daemon: no available IPv4 addresses on this network's address pools. - The container will be created, but not started.
- If you stop and delete another container, you’ll be able to start the failing container.
- Once the addresses have run out, you’ll get
- This is useful, because Container Manager doesn’t allow you to specify the IP address, even though it does allow you
to specify
macvlan0as the attached network. - You can get the assigned IP addresses with
sudo docker network inspect macvlan0 | jq '.[].Containers[] | {Name,IPv4Address}' - But you probably do want to specify an IP address. You want fixed IP addresses so you can put your containers in DNS, right?