Was macht die Option --net = host im Docker-Befehl wirklich?

95

Ich bin ein bisschen Anfänger in Docker. Ich konnte keine klare Beschreibung der Funktionsweise dieser Option im Docker-Ausführungsbefehl finden.

Können wir damit auf die Anwendungen zugreifen, die auf Docker-Containern ausgeführt werden, ohne einen Port anzugeben? Wenn ich beispielsweise eine Webanwendung ausführe, die über ein Docker-Image in Port 8080 mithilfe der Option -p 8080:8080im Docker-Ausführungsbefehl bereitgestellt wird , muss ich auf dem 8080-Port in Docker-Containern ip / theWebAppName darauf zugreifen. Aber ich kann mir nicht wirklich vorstellen, wie die --net=hostOption funktioniert.

Ravindu Fernando
quelle

Antworten:

129

Nach der Docker-Installation haben Sie standardmäßig 3 Netzwerke:

docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
f3be8b1ef7ce        bridge              bridge              local
fbff927877c1        host                host                local
023bb5940080        none                null                local

Ich versuche das einfach zu halten. Wenn Sie einen Container standardmäßig starten, wird er im Bridge-Netzwerk (Docker0) erstellt.

$ docker run -d jenkins
1498e581cdba        jenkins             "/bin/tini -- /usr..."   3 minutes ago       Up 3 minutes        8080/tcp, 50000/tcp   friendly_bell

In der Docker-Datei von Jenkins werden die Ports 8080und 50000freigelegt. Diese Ports werden für den Container in seinem Brückennetzwerk geöffnet. So kann alles in diesem Brückennetzwerk auf den Container am Port 8080und zugreifen 50000. Alles im Brückennetzwerk befindet sich im privaten Bereich von "Subnet": "172.17.0.0/16",Wenn Sie von außen darauf zugreifen möchten, müssen Sie die Ports zuordnen -p 8080:8080. Dadurch wird der Port Ihres Containers dem Port Ihres realen Servers (dem Host-Netzwerk) zugeordnet. 8080Wenn Sie also auf Ihren Server zugreifen, wird der Zugriff auf Ihr Bridgenetwork am Port erfolgen 8080.

Jetzt haben Sie auch Ihr Host-Netzwerk. Was die Containernetzwerke nicht containerisiert. Wenn Sie also einen Container im Host-Netzwerk starten, sieht er folgendermaßen aus (es ist der erste):

CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                 NAMES
1efd834949b2        jenkins             "/bin/tini -- /usr..."   6 minutes ago       Up 6 minutes                              eloquent_panini
1498e581cdba        jenkins             "/bin/tini -- /usr..."   10 minutes ago      Up 10 minutes       8080/tcp, 50000/tcp   friendly_bell

Der Unterschied liegt bei den Ports. Ihr Container befindet sich jetzt in Ihrem Host-Netzwerk. Wenn Sie also den Port 8080auf Ihrem Host öffnen, greifen Sie sofort auf den Container zu.

$ sudo iptables -I INPUT 5 -p tcp -m tcp --dport 8080 -j ACCEPT

Ich habe den Port 8080in meiner Firewall geöffnet und wenn ich jetzt auf meinen Server am Port 8080zugreife, greife ich auf meine Jenkins zu. Ich denke, dieser Blog ist auch nützlich, um es besser zu verstehen.

lvthillo
quelle
4
Ist es möglich, die Option --net=hostin eine Docker-Datei einzufügen?
AnirbanDebnath
6
@AnirbanDebnath Ich glaube nicht, dass es möglich ist, es in eine Docker-Datei zu schreiben, aber seit Docker v17 können Sie es als Parameter für Ihren Docker-Build verwenden : docker build --network=host. Das angegebene Host-Netzwerk für die Docker-Erstellung dient nur zum Herunterladen von Paketen, die zum Erstellen des Images erforderlich sind. Wenn Sie Ihren Container im Host-Netzwerk ausführen möchten, müssen Sie noch die Option --network = host definieren.
lvthillo
Ja @AnirbanDebnath, es ist in Dockerfile erlaubt. zB In v3 - network_mode: "host"(ref - docs.docker.com/compose/compose-file/#network_mode )
Mohnish
Dies ist eine Docker-Compose-Datei, in der beschrieben wird, wie der Container ausgeführt wird. Keine Docker-Datei. Aber in der Tat ist es möglich und macht dasselbe wie Docker run --network = host
lvthillo
29

Die --net=hostOption wird verwendet, um die Programme im Docker-Container aus Sicht des Netzwerks so aussehen zu lassen, als würden sie auf dem Host selbst ausgeführt. Dies ermöglicht dem Container einen größeren Netzwerkzugriff als normalerweise möglich.

Normalerweise müssen Sie Ports vom Host-Computer in einen Container weiterleiten. Wenn sich die Container jedoch das Netzwerk des Hosts teilen, erfolgt jede Netzwerkaktivität direkt auf dem Host-Computer - genau wie wenn das Programm lokal auf dem Host statt in einem ausgeführt würde Container.

Dies bedeutet zwar, dass Sie keine Ports mehr verfügbar machen und sie Container-Ports zuordnen müssen, aber Sie müssen Ihre Docker-Dateien bearbeiten, um die Ports anzupassen, die jeder Container abhört, um Konflikte zu vermeiden, da nicht zwei Container gleichzeitig ausgeführt werden können Host-Port. Der eigentliche Grund für diese Option ist jedoch die Ausführung von Apps, die einen Netzwerkzugriff benötigen, der nur schwer an einen Container auf Portebene weitergeleitet werden kann.

Wenn Sie beispielsweise einen DHCP-Server ausführen möchten, müssen Sie in der Lage sein, den Broadcast-Verkehr im Netzwerk abzuhören und die MAC-Adresse aus dem Paket zu extrahieren. Diese Informationen gehen während des Portweiterleitungsprozesses verloren. Die einzige Möglichkeit, einen DHCP-Server in Docker auszuführen, besteht darin, den Container als auszuführen --net=host.

Im Allgemeinen wird --net=hostes nur benötigt, wenn Sie Programme mit sehr spezifischen, ungewöhnlichen Netzwerkanforderungen ausführen.

Aus Sicherheitsgründen können Docker-Container viele Ports überwachen, obwohl sie nur einen einzelnen Port ankündigen (verfügbar machen). Normalerweise ist dies in Ordnung, da Sie nur den einzelnen erwarteten Port weiterleiten. Wenn Sie jedoch diesen verwenden --net=host, werden alle Ports des Containers auf dem Host überwacht, auch diejenigen, die nicht in der Docker-Datei aufgeführt sind. Dies bedeutet, dass Sie den Container genau prüfen müssen (insbesondere, wenn er nicht Ihnen gehört, z. B. einem offiziellen, der von einem Softwareprojekt bereitgestellt wird), um sicherzustellen, dass Sie nicht versehentlich zusätzliche Dienste auf dem Computer verfügbar machen.

Malvineous
quelle
Was wäre das Verhalten, wenn mehrere Container mit den Optionen '--net = host' gestartet würden? Werden Anfragen an einen zufälligen Container weitergeleitet?
user482594
@ user482594: Sie teilen sich alle denselben Netzwerkstapel, genau wie Sie alle Programme in demselben Container ausgeführt haben. Wenn Sie beispielsweise zwei Webserver ausführen, müssen Sie sicherstellen, dass diese unterschiedliche Ports überwachen. Andernfalls wird beim zweiten Container die Fehlermeldung angezeigt, dass der Port vom ersten verwendet wird. Eingehender Datenverkehr wird an den Container weitergeleitet, der auf ihn wartet (technisch gesehen sehen alle --net=hostContainer den Datenverkehr, aber natürlich kann jeweils nur ein Programm einen bestimmten Port überwachen, unabhängig davon, in welchem ​​Container Sie ihn ausführen ).
Malvineous
1
  1. Sie können Ihr eigenes neues Netzwerk wie --net = "anyname" erstellen.
  2. Dies geschieht, um die Dienste von verschiedenen Containern zu isolieren.
  3. Angenommen, derselbe Dienst wird in verschiedenen Containern ausgeführt, aber die Portzuordnung bleibt gleich. Der erste Container startet gut, aber der gleiche Dienst aus dem zweiten Container schlägt fehl. Um dies zu vermeiden, ändern Sie entweder die Portzuordnungen oder erstellen Sie ein Netzwerk.
Abhishek DK
quelle
1
Vielen Dank für die Erwähnung von "2. Dies geschieht, um die (Netzwerk-) Dienste von verschiedenen Containern zu isolieren". Ich sehe wirklich den Wert der Verwendung anderer Docker-Netzwerkkonfigurationen (außer host), wenn die Möglichkeit besteht, mehrere Container auf demselben Host auszuführen . In anderen Fällen (in denen keine Netzwerkisolation erforderlich ist) würde ich es vorziehen --net=host.
CᴴᴀZ