Eigenständige Anleitung, unabhängig von einzelnen Diensten – relevant für jeden Container auf Mimir, der eine eigene, “echte” LAN-IP braucht (Adblocker, Reverse Proxies mit eigener IP, etc.). Ursprünglich für AdGuard Home erarbeitet.

Warum Macvlan (statt Bridge)?

Docker-Standard ist Bridge-Netzwerk mit NAT – dabei erscheinen alle Container hinter derselben internen Bridge-IP, echte Client-IPs aus dem LAN gehen verloren. Für Anwendungsfälle, in denen ein Dienst als eigenständiges Gerät im LAN auftreten muss (z. B. AdGuard Home für Pro-Client-Erkennung), ist das ungeeignet.

Erkennungsmerkmal eines “falschen” Bridge-Netzwerks in Container Manager: Auch wenn du es ..._macvlan nennst – wenn in der GUI unter Treiber “bridge” steht und “IP Masquerade: Aktivieren” angezeigt wird, ist es kein echtes Macvlan. Die Container-Manager-GUI kann kein echtes Macvlan-Netzwerk erstellen – das geht ausschließlich per SSH.

Die zentrale Einschränkung von Macvlan

Der Host (die NAS selbst) kann seine eigenen Macvlan-Container nicht direkt erreichen – auch nicht über localhost oder Docker-interne Bridges. Das ist eine bewusste Kernel-Einschränkung (Isolation zwischen einem physischen Parent-Interface und seinen Macvlan-Kindern), keine Fehlkonfiguration.

Betrifft:

  • Die NAS selbst (Ping/Curl auf die Container-IP schlägt fehl)
  • Alle anderen Container auf derselben NAS, deren Traffic über die Host-Routingtabelle läuft (z. B. Bridge-Mode-Container wie NPM)

Nicht betroffen: Alle anderen Geräte im LAN (Laptop, Handy etc.) – die erreichen Macvlan-Container ganz normal, weil diese ja eine echte LAN-IP haben.

Setup-Daten (dieses Netz)

Wert
LAN-Subnetz172.16.46.0/24
Gateway172.16.46.1 (FritzBox)
Reservierter Macvlan-Bereich (Docker --ip-range, nur für Docker-interne Auto-Vergabe relevant, wir setzen aber immer feste IPs)172.16.46.200/29 (.200.207)
FritzBox-DHCP-Pooleingeschränkt auf .1–.199
Parent-Interfaceeth0 (kein Open vSwitch aktiv, daher nicht ovs_eth0)
Docker-Netzwerknamelan_macvlan
Host-Shim-IP172.16.46.206 (per --aux-address reserviert)
Statischer IP-Bereich für neue Container ab jetzt172.16.46.230–.239 (organisatorische Reservierung, kein Docker-Setting – siehe Konflikt-Abschnitt unten)

1. Docker-Macvlan-Netzwerk anlegen (per SSH)

sudo docker network create -d macvlan \
  --subnet=172.16.46.0/24 \
  --gateway=172.16.46.1 \
  --ip-range=172.16.46.200/29 \
  --aux-address 'host=172.16.46.206' \
  -o parent=eth0 lan_macvlan
  • --aux-address reserviert .206 exklusiv für den Host-Shim (siehe unten), damit Docker sie nicht versehentlich an einen Container vergibt.
  • Danach taucht lan_macvlan auch in Container Manager auf (Treiber: macvlan, kein Masquerade) und Container können ihr dort per GUI zugewiesen werden.

2. Container mit fester IP im Compose-File

services:
  meinservice:
    image: irgendein/image
    networks:
      lan_macvlan:
        ipv4_address: 172.16.46.201   # freie IP aus dem reservierten Bereich
    ...
 
networks:
  lan_macvlan:
    external: true

3. Host-Zugriff reparieren: Macvlan-Shim

Damit die NAS selbst (und darüber auch Bridge-Mode-Container wie NPM) die Macvlan-Container erreichen kann, braucht der Host ein eigenes virtuelles Interface im selben L2-Segment:

#!/bin/sh
 
# Kurze Wartezeit, damit eth0 beim Boot sicher bereit ist
sleep 15
 
# Shim-Interface anlegen (gebunden an dasselbe Parent-Interface wie das Docker-Netzwerk)
ip link add macvlan-shim link eth0 type macvlan mode bridge
 
# Host bekommt die reservierte Aux-Adresse
ip addr add 172.16.46.206/32 dev macvlan-shim
 
# Interface aktivieren
ip link set macvlan-shim up
 
# Route auf den gesamten Macvlan-Bereich über das Shim-Interface
ip route add 172.16.46.200/29 dev macvlan-shim

Als Boot-Task einrichten (Synology Taskplaner)

  1. Systemsteuerung → Taskplaner → Erstellen → Ausgelöste Aufgabe → Benutzerdefiniertes Skript
  2. Allgemein: Benutzer = root, Ereignis = Beim Start
  3. Aufgabeneinstellungen → Ausführen des Befehls: obiges Skript einfügen

Test ohne Neustart

# Skript einmalig manuell ausführen (als root), dann:
ip addr show macvlan-shim
ping 172.16.46.200   # IP eines Macvlan-Containers

Test, ob die Boot-Task wirklich greift (empfohlen!)

Nicht nur manuell testen – das sagt nichts über den echten Boot-Vorgang aus:

ip link del macvlan-shim      # sauberen Zustand simulieren
ping 172.16.46.200            # sollte jetzt fehlschlagen

Danach die Taskplaner-Aufgabe manuell auslösen (Rechtsklick → Ausführen, nicht das Skript direkt in der Shell!) und erneut prüfen. Der eigentliche Beweis ist aber ein echter Reboot.

Bekannte Stolperfalle: Adresse löschen reißt die Route mit

Wenn man testweise nur die IP vom Shim-Interface löscht:

ip addr del 172.16.46.206/32 dev macvlan-shim

verschwindet nicht nur die Adresse, sondern auch die zuvor gesetzte Route (ip route get zeigt danach wieder dev eth0 statt dev macvlan-shim). Das Wiederherstellen der Adresse allein reicht dann nicht – die Route muss explizit neu gesetzt werden:

ip addr add 172.16.46.206/32 dev macvlan-shim
ip route add 172.16.46.200/29 dev macvlan-shim

Für das Boot-Skript ist das irrelevant, da dort ohnehin beide Befehle bei jedem Start neu ausgeführt werden – die Falle tritt nur beim manuellen Herumprobieren im laufenden Betrieb auf.

4. Bridge-Mode-Container erreichen Macvlan-Container automatisch

Sobald der Shim aktiv ist, profitieren auch andere Container (z. B. NPM im normalen Bridge-Modus mit Portmapping) automatisch mit – deren Traffic zu Macvlan-IPs läuft über die Host-Routingtabelle, die jetzt korrekt auf macvlan-shim zeigt. Keine zusätzliche Netzwerk-Konfiguration am jeweiligen Container nötig.

Quick-Check:

docker exec -it <container-name> curl -I http://172.16.46.200:<port>

Verwendet in

⚠️ Konflikt mit FritzBox WireGuard-VPN (entdeckt 2026-07)

Die FritzBox vergibt für jeden neuen WireGuard-VPN-Tunnel automatisch eine IP aus dem LAN – ohne manuelle Vergabe- oder Ausschluss-Möglichkeit. Sie nimmt dabei die erste ARP-unsichtbare (= nicht aktiv antwortende) Adresse direkt oberhalb der DHCP-Pool-Grenze (.199). Reservierte, aber noch nicht durch einen laufenden Container belegte Macvlan-IPs sind für die FritzBox unsichtbar und werden dadurch für VPN-Tunnel eingesammelt.

Passiert: 172.16.46.201, .202, .203, .205 wurden von vier WireGuard-Geräteverbindungen belegt, obwohl im reservierten Docker-Bereich (172.16.46.200/29). Nur .200 (AdGuard) und .206 (Shim) waren durch aktive Container/Interfaces geschützt.

Konsequenz: Diese vier IPs sind dauerhaft an die VPN-Tunnel gebunden (FritzOS erlaubt keine nachträgliche Änderung der VPN-Client-IP außer Löschen+Neuanlegen des Zugangs).

Entscheidung für künftige Macvlan-Container: Neuer, klar getrennter Reservierungsbereich mit Puffer zur DHCP-Pool-Grenze, statt direkt angrenzend:

DHCP-Pool FritzBoxbleibt .1–.199
Bereits durch VPN belegt.201, .202, .203, .205 – nicht mehr für Docker nutzen
Neuer Docker-Reservierungsbereich.230–.239 (reichlich Puffer, weitere VPN-Geräte sind unwahrscheinlich, aber übliche Praxis: lieber zu viel Abstand als zu wenig)

Für mehr Robustheit bei künftigen Containern: Feste mac_address: im Compose-File setzen und die IP vor dem Deployment manuell als Gerät in der FritzBox eintragen (Heimnetz → Netzwerk → Gerät hinzufügen, „IP-Adresse immer diesem Netzwerkgerät zuweisen”). Damit gilt die IP als bekannt/reserviert, auch bevor der Container läuft und ARP-sichtbar ist – verhindert eine Wiederholung dieses Problems, sobald mal mehr VPN-Geräte dazukommen.