Docker macvlan routing issues – How to fix other networks/VPNs that cannot reach your macvlan container.
This is written to fix macvlan connectivity for VPN connections on the same server (VPN server and Docker container with macvlan on the same host).
In my example, I used Netbird VPN. But the same problem applies for a vanilla WireGuard setup. Actually, this fixed two tunnels for me: native WireGuard S2S and Netbird Mesh VPN.

The solution:
# Create the bridge (one time or via service)
sudo ip link add macvlan-shim link eno1 type macvlan mode bridge
sudo ip addr add 10.5.5.245/32 dev macvlan-shim
sudo ip link set macvlan-shim up
# The Specific Route that fixed everything
sudo ip route add 10.5.5.4/32 dev macvlan-shim
And this… can be (semi)automated, of course!
This script will find all your Docker containers using the macvlan network. If you have multiple, you must adjust the script.
Create a script file:
nano refresh-macvlan-routes.sh
“NETWORK_NAME” is your one network (e.g. “ownNetv2”) for macvlan (the one that is your home local network IP, like “10.5.5.0/24”.
“SHIM_NAME” is just the name of the new “bridge/shim” interface.
“SHIM_IP” is the IP in your (local home) network.
“PARENT_IF” is your physical interface name.
The Code:
#!/bin/bash
# --- CONFIGURATION ---
# Check your network name with 'docker network ls'
NETWORK_NAME="ownNetv2"
SHIM_NAME="macvlan-shim"
PARENT_IF="eno1"
SHIM_IP="10.5.5.245/32"
# ---------------------
# 1. Ensure the Shim exists
if ! ip link show "$SHIM_NAME" > /dev/null 2>&1; then
echo "Creating $SHIM_NAME..."
ip link add "$SHIM_NAME" link "$PARENT_IF" type macvlan mode bridge
ip addr add "$SHIM_IP" dev "$SHIM_NAME"
ip link set "$SHIM_NAME" up
fi
# 2. Clear old /32 routes from this shim to avoid duplicates
ip route show dev "$SHIM_NAME" | grep "/32" | awk '{print $1}' | xargs -I {} ip route del {} dev "$SHIM_NAME" 2>/dev/null
# 3. Get IPs of containers ONLY on the macvlan network
CONTAINER_IPS=$(docker network inspect "$NETWORK_NAME" -f '{{range .Containers}}{{.IPv4Address}}{{println}}{{end}}' | cut -d'/' -f1)
# 4. Add the specific routes
for IP in $CONTAINER_IPS; do
if [[ $IP =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "Routing Macvlan Container $IP via $SHIM_NAME"
ip route add "$IP/32" dev "$SHIM_NAME"
fi
done
Of course this approach could be automated further. Like with a systemd Timer.
sudo nano /usr/local/bin/refresh-macvlan-routes.sh
(PASTE THE SCRIPT)
sudo chmod +x /usr/local/bin/refresh-macvlan-routes.sh
File: /etc/systemd/system/macvlan-refresh.service
[Unit]
Description=Refresh Macvlan Routing Table
After=docker.service
[Service]
Type=oneshot
ExecStart=/usr/local/bin/refresh-macvlan-routes.sh
[Install]
WantedBy=multi-user.target
File: /etc/systemd/system/macvlan-refresh.timer
[Unit]
Description=Run Macvlan Refresh Script Periodically
[Timer]
# Wait 5 minutes after the system boots up before running the first time
OnBootSec=5min
# Then run it again every 1 hour (you can change this to 1day, 5min, etc.)
OnUnitActiveSec=1h
# Keep the schedule even if the system was asleep
Persistent=true
[Install]
WantedBy=timers.target
Enable the Timer
sudo systemctl daemon-reload
sudo systemctl enable –now macvlan-refresh.timer
Helpful Commands
- Check when it will run next:
systemctl list-timers macvlan-refresh.timer - Run it manually right now:
sudo systemctl start macvlan-refresh.service - Check the logs:
journalctl -u macvlan-refresh.service
0 Comments