Docker-Netzwerk-Grundlagen

DockerBeginner
Jetzt üben

Einführung

In diesem Lab werden wir die Grundlagen des Docker-Networkings erkunden. Docker-Netzwerke ermöglichen es Containern, untereinander und mit der Außenwelt zu kommunizieren. Wir werden verschiedene Netzwerktypen behandeln, benutzerdefinierte Netzwerke erstellen, Container miteinander verbinden und Netzwerkkonfigurationen verwalten. Diese praktische Erfahrung wird Ihnen ein solides Fundament in den Konzepten und Praktiken des Docker-Networkings vermitteln.

Docker-Netzwerktypen verstehen

Docker bietet mehrere integrierte Netzwerktreiber. Beginnen wir damit, die Standardnetzwerke auf Ihrem System zu untersuchen.

Führen Sie in Ihrem Terminal den folgenden Befehl aus, um alle verfügbaren Docker-Netzwerke aufzulisten:

docker network ls

Dieser Befehl listet alle Netzwerke auf, die Docker auf Ihrem System erstellt hat. Sie sollten eine Ausgabe ähnlich dieser sehen:

NETWORK ID     NAME      DRIVER    SCOPE
79dce413aafd   bridge    bridge    local
91199fc6ad2e   host      host      local
1078d2c781b6   none      null      local

Hier ist eine Erläuterung der Standard-Netzwerktypen:

  1. bridge: Dies ist der Standard-Netzwerktreiber. Wenn Sie einen Container starten, ohne ein Netzwerk anzugeben, verbindet er sich automatisch mit dem Bridge-Netzwerk. Container im selben Bridge-Netzwerk können über ihre IP-Adressen miteinander kommunizieren.

  2. host: Dieser Treiber hebt die Netzwerisolation zwischen dem Container und dem Docker-Host auf. Der Container teilt sich den Netzwerk-Namespace des Hosts, was bedeutet, dass er die IP-Adresse und den Port-Bereich des Hosts direkt nutzt. Dies kann nützlich sein, um die Performance in bestimmten Szenarien zu optimieren.

  3. none: Dieser Treiber deaktiviert jegliches Networking für einen Container. Container, die diesen Netzwerktyp verwenden, haben keinen Zugriff auf externe Netzwerke oder andere Container. Dies ist sinnvoll, wenn Sie einen Container vollständig isolieren möchten.

Die Spalte SCOPE gibt an, ob das Netzwerk auf einen einzelnen Host beschränkt ist (local) oder sich über mehrere Hosts in einem Docker Swarm erstrecken kann (swarm).

Das Standard-Bridge-Netzwerk untersuchen

Nachdem wir die Liste der Netzwerke gesehen haben, schauen wir uns das Standard-Bridge-Netzwerk genauer an. Dieses Netzwerk wird automatisch von Docker erstellt und von Containern verwendet, sofern nichts anderes angegeben ist.

Führen Sie den folgenden Befehl aus, um das Bridge-Netzwerk zu inspizieren:

docker network inspect bridge

Dieser Befehl liefert detaillierte Informationen über das Bridge-Netzwerk, einschließlich Subnetz, Gateway und verbundene Container. Sie sehen eine Ausgabe ähnlich dieser (aus Gründen der Übersichtlichkeit gekürzt):

[
  {
    "Name": "bridge",
    "Id": "79dce413aafdd7934fa3c1d0cc97decb823891ce406442b7d51be6126ef06a5e",
    "Created": "2024-08-22T09:58:39.747333789+08:00",
    "Scope": "local",
    "Driver": "bridge",
    "EnableIPv6": false,
    "IPAM": {
      "Driver": "default",
      "Options": null,
      "Config": [
        {
          "Subnet": "172.17.0.0/16",
          "Gateway": "172.17.0.1"
        }
      ]
    },
    "Internal": false,
    "Attachable": false,
    "Ingress": false,
    "ConfigFrom": {
      "Network": ""
    },
    "ConfigOnly": false,
    "Containers": {},
    "Options": {
      "com.docker.network.bridge.default_bridge": "true",
      "com.docker.network.bridge.enable_icc": "true",
      "com.docker.network.bridge.enable_ip_masquerade": "true",
      "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
      "com.docker.network.bridge.name": "docker0",
      "com.docker.network.driver.mtu": "1500"
    },
    "Labels": {}
  }
]

Lassen Sie uns einige wichtige Informationen aus dieser Ausgabe analysieren:

  • Subnet: Das von Containern in diesem Netzwerk verwendete Subnetz ist 172.17.0.0/16. Das bedeutet, dass Containern IP-Adressen innerhalb dieses Bereichs zugewiesen werden.
  • Gateway: Das Gateway für dieses Netzwerk ist 172.17.0.1. Dies ist die IP-Adresse, die Container verwenden, um mit Netzwerken außerhalb ihres eigenen Bereichs zu kommunizieren.
  • Containers: Dieses Feld ist leer, da wir noch keine Container gestartet haben.
  • Options: Dies sind verschiedene Konfigurationsoptionen für das Bridge-Netzwerk. Zum Beispiel bedeutet enable_icc auf "true", dass die Kommunikation zwischen Containern (Inter-Container Communication) in diesem Netzwerk erlaubt ist.

Das Verständnis dieser Informationen ist entscheidend bei der Fehlersuche in Netzwerken oder wenn Sie Ihre Container so konfigurieren müssen, dass sie mit spezifischen IP-Bereichen kommunizieren.

Ein benutzerdefiniertes Bridge-Netzwerk erstellen

Während das Standard-Bridge-Netzwerk für viele Anwendungsfälle ausreicht, ermöglicht das Erstellen benutzerdefinierter Netzwerke eine bessere Isolierung und Kontrolle. Benutzerdefinierte Netzwerke sind besonders nützlich, wenn Sie zusammengehörige Container gruppieren möchten oder steuern müssen, welche Container miteinander kommunizieren dürfen.

Erstellen wir ein benutzerdefiniertes Bridge-Netzwerk namens my-network:

docker network create --driver bridge my-network

Dieser Befehl erstellt ein neues Bridge-Netzwerk. Die Option --driver bridge ist hier eigentlich optional, da Bridge der Standardtreiber ist, wird aber zur Verdeutlichung mit angegeben.

Verifizieren wir nun, dass unser neues Netzwerk erstellt wurde:

docker network ls

Sie sollten my-network in der Liste der Netzwerke sehen:

NETWORK ID     NAME         DRIVER    SCOPE
1191cb61c989   bridge       bridge    local
91199fc6ad2e   host         host      local
47ac4e684a72   my-network   bridge    local
1078d2c781b6   none         null      local

Unser neues my-network erscheint in der Liste, was bestätigt, dass es erfolgreich erstellt wurde. Dieses Netzwerk steht nun für Container zur Verfügung.

Container mit Netzwerken verbinden

Da wir nun unser benutzerdefiniertes Netzwerk haben, erstellen wir zwei Container und verbinden sie damit. Wir verwenden für dieses Beispiel das nginx-Image, das einen leichtgewichtigen Webserver bereitstellt.

Führen Sie die folgenden Befehle aus, um zwei Container zu erstellen:

docker run -d --name container1 --network my-network nginx
docker run -d --name container2 --network my-network nginx

Lassen Sie uns diese Befehle aufschlüsseln:

  • -d: Dieses Flag führt den Container im Detached-Modus aus, d. h. er läuft im Hintergrund.
  • --name: Dies weist unserem Container einen Namen zu, was die spätere Referenzierung erleichtert.
  • --network: Dies gibt an, mit welchem Netzwerk der Container verbunden werden soll.
  • nginx: Dies ist der Name des Images, das wir zur Erstellung unserer Container verwenden.

Diese Befehle erstellen zwei im Hintergrund laufende Container namens container1 und container2, die beide mit unserem my-network verbunden sind.

Überprüfen wir, ob die Container laufen und mit unserem Netzwerk verbunden sind:

docker ps

Dieser Befehl listet alle laufenden Container auf. Sie sollten beide Container in der Ausgabe sehen:

CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS     NAMES
1234567890ab   nginx     "/docker-entrypoint.…"   10 seconds ago   Up 9 seconds    80/tcp    container2
abcdef123456   nginx     "/docker-entrypoint.…"   20 seconds ago   Up 19 seconds   80/tcp    container1

Diese Ausgabe zeigt, dass beide Container das Nginx-Image ausführen und den Port 80 innerhalb des Containers bereitstellen.

Kommunikation zwischen Containern testen

Einer der Hauptvorteile des Docker-Networkings besteht darin, dass Container im selben Netzwerk unter Verwendung ihrer Containernamen als Hostnamen miteinander kommunizieren können. Dies macht es einfach, die Kommunikation zwischen Diensten einzurichten, ohne deren IP-Adressen kennen zu müssen.

Testen wir dies, indem wir von container1 aus eine Anfrage an container2 senden:

docker exec container1 curl -s container2

Lassen Sie uns diesen Befehl aufschlüsseln:

  • docker exec: Dies weist Docker an, einen Befehl innerhalb eines laufenden Containers auszuführen.
  • container1: Dies ist der Name des Containers, in dem wir den Befehl ausführen möchten.
  • curl -s container2: Dies ist der Befehl, den wir im Container ausführen. Er sendet eine GET-Anfrage an container2, und das Flag -s sorgt dafür, dass curl im Silent-Modus arbeitet.

Dieser Befehl führt den curl-Befehl innerhalb von container1 aus und sendet eine Anfrage an container2. Sie sollten den HTML-Code der Standard-Nginx-Willkommensseite in der Ausgabe sehen:

<!doctype html>
<html>
  <head>
    <title>Welcome to nginx!</title>
    <style>
      html {
        color-scheme: light dark;
      }
      body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
      }
    </style>
  </head>
  <body>
    <h1>Welcome to nginx!</h1>
    <p>
      If you see this page, the nginx web server is successfully installed and
      working. Further configuration is required.
    </p>

    <p>
      For online documentation and support please refer to
      <a href="http://nginx.org/">nginx.org</a>.<br />
      Commercial support is available at
      <a href="http://nginx.com/">nginx.com</a>.
    </p>

    <p><em>Thank you for using nginx.</em></p>
  </body>
</html>

Diese erfolgreiche Antwort zeigt, dass container1 mit container2 über dessen Containernamen kommunizieren kann. Der eingebettete DNS-Server von Docker löst den Containernamen in seine IP-Adresse innerhalb des Netzwerks auf.

Container-Ports freigeben

Standardmäßig können Container in einem benutzerdefinierten Netzwerk miteinander kommunizieren, sind aber von außerhalb des Docker-Hosts nicht erreichbar. Um einen Container vom Host oder von externen Netzwerken aus zugänglich zu machen, müssen wir seine Ports freigeben (exponieren).

Erstellen wir einen neuen Container mit einem freigegebenen Port:

docker run -d --name exposed-container -p 8080:80 --network my-network nginx

Lassen Sie uns diesen Befehl aufschlüsseln:

  • -d: Führt den Container im Detached-Modus aus.
  • --name exposed-container: Benennt den Container "exposed-container".
  • -p 8080:80: Verknüpft Port 80 innerhalb des Containers mit Port 8080 auf dem Host.
  • --network my-network: Verbindet den Container mit unserem benutzerdefinierten Netzwerk.
  • nginx: Verwendet das Nginx-Image.

Dieser Befehl erstellt einen neuen Container namens exposed-container, leitet den Port 80 des Containers auf den Port 8080 des Hosts weiter und verbindet ihn mit unserem my-network.

Nun können Sie auf den Nginx-Server dieses Containers von Ihrem Host-Rechner aus zugreifen, indem Sie einen Webbrowser öffnen und zu http://localhost:8080 navigieren oder curl verwenden:

curl localhost:8080

Sie sollten denselben HTML-Code der Nginx-Willkommensseite wie zuvor sehen. Diesmal greifen wir jedoch direkt vom Host auf den Container zu, nicht von einem anderen Container aus.

Host-Networking verwenden

Für Szenarien, in denen ein Container den Netzwerk-Stack des Hosts teilen soll, können Sie den Host-Netzwerktreiber verwenden. Dies hebt die Netzwerkisolation zwischen dem Container und dem Host auf, was für bestimmte Anwendungen nützlich sein kann, aber aufgrund potenzieller Port-Konflikte mit Vorsicht zu genießen ist.

Erstellen wir einen Container mit Host-Networking:

docker run -d --name host-networked --network host nginx

Dieser Befehl erstellt einen neuen Container namens host-networked unter Verwendung des Host-Netzwerks. Beachten Sie, dass Sie bei Host-Networking -p nicht verwenden können, da der Container bereits die Netzwerkschnittstellen des Hosts nutzt.

Um zu überprüfen, ob der Container Host-Networking verwendet, können wir seine Netzwerkeinstellungen inspizieren:

docker inspect --format '{{.HostConfig.NetworkMode}}' host-networked

Dieser Befehl inspiziert den Container und formatiert die Ausgabe so, dass nur der NetworkMode angezeigt wird. Es sollte host ausgegeben werden, was bestätigt, dass der Container Host-Networking verwendet.

Bei der Verwendung von Host-Networking teilt sich der Container die IP-Adresse des Hosts und kann direkt auf alle Netzwerkschnittstellen des Hosts zugreifen. Dies kann zur Maximierung der Performance nützlich sein, bedeutet aber auch, dass alle vom Container verwendeten Ports direkt auf dem Host geöffnet werden, was zu Konflikten führen kann, wenn man nicht vorsichtig ist.

Zusammenfassung

In diesem Lab haben wir die Grundlagen des Docker-Networkings erkundet. Wir haben verschiedene Netzwerktypen behandelt, benutzerdefinierte Netzwerke erstellt, Container verbunden, die Kommunikation zwischen Containern getestet, Container-Ports freigegeben und Host-Networking verwendet. Diese Konzepte bilden die Grundlage des Docker-Networkings und sind für das Design und die Verwaltung von containerisierten Anwendungen unerlässlich.

Wir haben gelernt, wie man:

  • Docker-Netzwerke auflistet und inspiziert
  • Benutzerdefinierte Bridge-Netzwerke erstellt
  • Container mit Netzwerken verbindet
  • Die Kommunikation zwischen Containern testet
  • Container-Ports für den Host freigibt
  • Host-Networking für Container verwendet

Das Verständnis dieser Netzwerkkonzepte wird Ihnen helfen, robustere und sicherere containerisierte Anwendungen zu entwerfen. Während Sie weiter mit Docker arbeiten, werden Sie auf fortgeschrittenere Netzwerkszenarien stoßen, aber die hier behandelten Prinzipien dienen als solides Fundament für Ihren Weg in die Container-Orchestrierung und Microservices-Architektur.

Denken Sie daran, dass Docker-Networking ein leistungsstarkes Werkzeug ist, das es Ihnen ermöglicht, isolierte Umgebungen für Ihre Anwendungen zu schaffen und gleichzeitig eine kontrollierte Kommunikation zwischen Containern sowie mit der Außenwelt zu ermöglichen. Üben Sie diese Konzepte und erkunden Sie fortgeschrittenere Themen, um ein Experte in der Verwaltung von Docker-Netzwerken zu werden.