Mehrere Container sollen sich auf einem Dockerserver identische Ports verwenden. Eine Möglichkeit wäre es, über einen anderen Port den internen Port des Containers freizugeben (-p 8080:80). Es gibt jedoch Dienste, bei denen das nicht funktioniert, da der konsumierende Client ausschließlich auf einen bestimmten Port hört, da er so programmiert ist. Will man nun bspw. sowohl Adguard Home und pi-hole -beides DNS-Server, die auf Port 53 ihre Dienste anbieten- auf einem Server betreiben, führt das zu einem Konflikt!
Umgehen kann man das, indem man ein eigenes Netzwerk vom Typ macvlan erstellt.
Dieses Netz wird im selben Adressbereich wie das darüberliegende Netz erstellt und sämtlicher Netzwerkverkehr wird über ein Gateway geschickt. Der Adressbereich, in dem die Netzwerkadressen vergeben werden, muss vorab definiert werden, da intern das macvlan-Netzwerk DHCP-Adressen vergibt. Es überschneidet sich mit dem Bereich des darüberliegenden DHCP-Adressbereichs. Sie müssen also überlappungsfrei ausgesteuert werden. In meinem Beispiel besteht der Adressbereich aus genau einer Adresse. Für andere Clients sieht es nun so aus, als sei eine Nummer vergeben worden, es handelt sich aber um ein gekapseltes Netz mit dieser einen IP-Adresse
Erzeugt wird das Netzwerk mit diesem Befehl:
docker network create -d macvlan --subnet 192.168.4.0/24 --gateway 192.168.4.1 --ip-range 192.168.4.250/32 -o parent=ens18 mymacvlan
- Listeneintrag-d macvlan ist dabei der Treiber
- das subnet und das gateway enthält den Nummernbereich, in dem man sich bewegt. Hierdrin gibt es einen eigenen, von Docker gesteuerten DHCP-Server, der eigene Nummern (und damit ärgerlicherweise zuerst 192.168.4.1) vergibt
- der ip-range sorgt deshalb dafür, dass der interne, dockereigene DHCP-Server nur Nummern aus dem festgelegten Range (und damit hier genau diese eine IP-Adresse) vergibt.
- -o ens18 gibt die IP-Adresse des darüberliegenden Servers wieder. Hierüber wird geroutet.
Nun kann der Container mit Verweis auf dieses Netzwerk gestartet werden. Dazu muss der --network-Parameter mitgegeben werden. Exemplarisch kann ein nginx so gestartet werden
docker run --rm -d --name mynginx2 --network mymacvlan nginx
Der Container mynginx2 bekommt nun die Adresse 192.168.4.250. Er ist nicht per Ping erreichbar, da es ja ein Subnet ist, funktioniert jedoch, wenn per 192.168.4.250:80 angesprochen werden, da dieser Port ja vom Container bereitgestellt wird.
Limitierend ist, dass lediglich ein macvlan je Parent-Adresse erstellt werden kann. Da hier ein 32er-Netz erstellt wurde, gibt es eben genau diese eine Adresse. Will man mehrere Adressen haben, könnte man bspw. 192.168.4.250/29 angeben. Der DHCP-Server des macvlans kann nun 6 Adressen vergeben!