Docker 2024 04/Networking: Unterschied zwischen den Versionen
Drlue (Diskussion | Beiträge) |
Drlue (Diskussion | Beiträge) |
||
| (4 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt) | |||
| Zeile 48: | Zeile 48: | ||
{{BML|code= | {{BML|code= | ||
#Baseimage | #Baseimage | ||
FROM | FROM example5:1.0 | ||
RUN apt-get update | RUN apt-get update | ||
RUN apt-get install -y curl inetutils-ping iproute2 | RUN apt-get install -y curl inetutils-ping iproute2 | ||
| Zeile 59: | Zeile 59: | ||
==== Image erstellen ==== | ==== Image erstellen ==== | ||
{{BML|code= | {{BML|code= | ||
docker build . -t | docker build . -t networking_example2:1.0 | ||
}} | }} | ||
| Zeile 65: | Zeile 65: | ||
{{BML|code= | {{BML|code= | ||
#Container mit Hostname A | #Container mit Hostname A | ||
docker run --name networkingA --hostname A --rm -d | docker run --name networkingA --hostname A --rm -d networking_example2:1.0 | ||
#Container mit Hostname B | #Container mit Hostname B | ||
docker run --name networkingB --hostname B --rm -d | docker run --name networkingB --hostname B --rm -d networking_example2:1.0 | ||
}} | }} | ||
==== Container | ==== Bash in Container starten ==== | ||
'''Terminal 1 - Networking A''' | '''Terminal 1 - Networking A''' | ||
{{BML|code= | {{BML|code= | ||
| Zeile 114: | Zeile 114: | ||
Die DNS Auflösung über '''Docker DNS''' funktioniert '''NICHT''' im default Bridge Netzwerk. | Die DNS Auflösung über '''Docker DNS''' funktioniert '''NICHT''' im default Bridge Netzwerk. | ||
=== Beispiel 3): Container | === Beispiel 3): Container Kommunikation === | ||
Im folgenden wird ein Docker Bridge Netzwerk erstellt. | Im folgenden wird ein Docker Bridge Netzwerk erstellt. | ||
| Zeile 124: | Zeile 124: | ||
{{BML|code= | {{BML|code= | ||
#Container mit Hostname A | #Container mit Hostname A | ||
docker run --name networkingA --network network_example2 --hostname A --rm -d | docker run --name networkingA --network network_example2 --hostname A --rm -d networking_example2:1.0 | ||
#Container mit Hostname B | #Container mit Hostname B | ||
docker run --name networkingB --network network_example2 --hostname B --rm -d | docker run --name networkingB --network network_example2 --hostname B --rm -d networking_example2:1.0 | ||
#Container mit Hostname C, als Veranschaulichung der Container Isolierung, verwendet default Bridge | #Container mit Hostname C, als Veranschaulichung der Container Isolierung, verwendet default Bridge | ||
docker run --name networkingC --hostname C --rm -d | docker run --name networkingC --hostname C --rm -d networking_example2:1.0 | ||
}} | }} | ||
==== Bash starten ==== | ==== Bash in Container starten ==== | ||
'''Terminal 1 - Networking A''' | '''Terminal 1 - Networking A''' | ||
| Zeile 189: | Zeile 189: | ||
## Kommunikation: Anwendung | ## Kommunikation: Anwendung | ||
=== Netzwerke erstellen === | ==== Netzwerke erstellen ==== | ||
Reverseproxy ---> Netzwerk tier1 <--- Anwendung ---> Netzwerk tier2 <--- Datenbank | Reverseproxy ---> Netzwerk tier1 <--- Anwendung ---> Netzwerk tier2 <--- Datenbank | ||
{{BML|code= | {{BML|code= | ||
| Zeile 196: | Zeile 196: | ||
}} | }} | ||
=== Container starten === | ==== Container starten ==== | ||
{{BML|code= | {{BML|code= | ||
#Reverseproxy | #Reverseproxy | ||
docker run --name reverseproxy --network tier1 --hostname reverseproxy --rm -d | docker run --name reverseproxy --network tier1 --hostname reverseproxy --rm -d networking_example2:1.0 | ||
#App | #App | ||
docker run --name app --network tier1 --hostname app --rm -d | docker run --name app --network tier1 --hostname app --rm -d networking_example2:1.0 | ||
#Netzwerk muss mit Container verbunden werden | #Netzwerk muss mit Container verbunden werden | ||
docker network connect tier2 app | docker network connect tier2 app | ||
#Db | #Db | ||
docker run --name db --network tier2 --hostname db --rm -d | docker run --name db --network tier2 --hostname db --rm -d networking_example2:1.0 | ||
}} | }} | ||
| Zeile 247: | Zeile 247: | ||
#Der Host Parameter kann weggelassen werden, dieser wird vom Host übernommen | #Der Host Parameter kann weggelassen werden, dieser wird vom Host übernommen | ||
#Etwaige Port Weiterleitungen entfallen, bzw. werden nicht berücksichtigt | #Etwaige Port Weiterleitungen entfallen, bzw. werden nicht berücksichtigt | ||
docker run --name networkingHost --network host --rm -d | docker run --name networkingHost --network host --rm -d networking_example2:1.0 | ||
}} | }} | ||
Aktuelle Version vom 19. April 2024, 05:39 Uhr
Folgendes soll einen Grundlegenden Überblick über das Container Networking bieten.
Netzwerk Treiber
Docker verwendet für die Netzwerkkommunikation Treiber. Folgende Treiber sind standardmäßig Verfügbar. Im folgenden werden wir uns auf die Netzwerktypen Host und Bridge beschränken.
bridge: The default network driver. If you don't specify a driver, this is the type of network you are creating. Bridge networks are commonly used when your application runs in a container that needs to communicate with other containers on the same host.
host: Remove network isolation between the container and the Docker host, and use the host's networking directly.
overlay: Overlay networks connect multiple Docker daemons together and enable Swarm services and containers to communicate across nodes. This strategy removes the need to do OS-level routing.
ipvlan: IPvlan networks give users total control over both IPv4 and IPv6 addressing. The VLAN driver builds on top of that in giving operators complete control of layer 2 VLAN tagging and even IPvlan L3 routing for users interested in underlay network integration.
macvlan: Macvlan networks allow you to assign a MAC address to a container, making it appear as a physical device on your network. The Docker daemon routes traffic to containers by their MAC addresses. Using the macvlan driver is sometimes the best choice when dealing with legacy applications that expect to be directly connected to the physical network, rather than routed through the Docker host's network stack.
none: Completely isolate a container from the host and other containers. none is not available for Swarm services.
Beispiel 1): Default Bridge
Wird ein Container über docker run ohne weitere Netzwerkkonfiguration gestartet, so verwendet dieser den bridge Netzwerktreiber.
Dies kann anhand von folgendem Beispiel nachvollzogen werden:
#Starten eines Containers
docker run --name ubuntu -it --rm -d ubuntu:22.04 bash
#Inspizieren des Containers
docker inspect ubuntu
...
"NetworkID": "026a89529e7e830967b50e7b79099229815bb1e0de6363d47f0e779873e27c70",
...
#Auflisten der Docker Netzwerke
docker network ls
NETWORK ID NAME DRIVER SCOPE
...
026a89529e7e bridge bridge local
...
Anhand der NetworkID kann nachvollzogen werden, dass der neu gestartete Container das Netzwerk mit dem Namen bridge verwendet. Hierbei handelt es sich um das default Bridge Netzwerk.
Daraus resultiert, dass alle Container die mit docker run ohne expliziten Netzwerk Parameter Teil dieses Netzwerks sind. Diese können auch untereinander miteinander kommunizieren.
Beispiel 2): Container Communication
Im folgenden wird das vorhergehende Beispiel um diverse Netzwerktools erweitert.
Dockerfile
Inhalt in Datei Dockerfile
#Baseimage
FROM example5:1.0
RUN apt-get update
RUN apt-get install -y curl inetutils-ping iproute2
#Standard Webseite erstellen
RUN mkdir -p /var/www
RUN echo "<html><h1>Welcome</h1></html>" > /var/www/index.html
#Der Entrypoint aus dem Baseimage wird verwendet
Image erstellen
docker build . -t networking_example2:1.0
Container starten
#Container mit Hostname A
docker run --name networkingA --hostname A --rm -d networking_example2:1.0
#Container mit Hostname B
docker run --name networkingB --hostname B --rm -d networking_example2:1.0
Bash in Container starten
Terminal 1 - Networking A
#Bash starten
docker exec -it networkingA bash
#IP Adresse des Containers ermitteln
ip addr
...
77: eth0@if78: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:04 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.4/16 brd 172.17.255.255 scope global eth0
...
#Container B ist erreichbar
ping 172.17.0.5
#Webseite von Container B abrufen
curl 172.17.0.5
<html><h1>Welcome</h1></html>
#Namensauflösung
ping B
ping: unknown host
Terminal 2 - Terminal B
#Bash starten
docker exec -it networkingB bash
#IP Adresse des Containers ermitteln
ip addr
...
79: eth0@if80: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:05 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.5/16 brd 172.17.255.255 scope global eth0
...
#Container A ist erreichbar
ping 172.17.0.4
#Webseite von Container A abrufen
curl 172.17.0.4
<html><h1>Welcome</h1></html>
#Namensauflösung
ping A
ping: unknown host
Die DNS Auflösung über Docker DNS funktioniert NICHT im default Bridge Netzwerk.
Beispiel 3): Container Kommunikation
Im folgenden wird ein Docker Bridge Netzwerk erstellt.
Bridge Netzwerk erstellen
docker network create network_example2
Container starten
Verwenden des Netzwerks:
#Container mit Hostname A
docker run --name networkingA --network network_example2 --hostname A --rm -d networking_example2:1.0
#Container mit Hostname B
docker run --name networkingB --network network_example2 --hostname B --rm -d networking_example2:1.0
#Container mit Hostname C, als Veranschaulichung der Container Isolierung, verwendet default Bridge
docker run --name networkingC --hostname C --rm -d networking_example2:1.0
Bash in Container starten
Terminal 1 - Networking A
#Bash starten
docker exec -it networkingB bash
curl B
<html><h1>Welcome</h1></html>
#Namensauflösung
ping B
#IP ermitteln
ip addr
inet 172.21.0.2/16 brd 172.21.255.255 scope global eth0
#Keine Route zu C
ping 172.17.0.4
Terminal 2 - Networking B
#Bash starten
docker exec -it networkingB bash
curl A
<html><h1>Welcome</h1></html>
#Namensauflösung
ping A
#IP ermitteln
ip addr
inet 172.21.0.3/16 brd 172.21.255.255 scope global eth0
#Keine Route zu C
ping 172.17.0.4
Terminal 3 - Networking C
#Bash starten
docker exec -it networkingC bash
#IP ermitteln
ip addr
inet 172.17.0.4/16 brd 172.17.255.255 scope global eth0
#Keine Route zu A oder B
ping 172.21.0.2
ping 172.21.0.3
Wie zu sehen ist, ist der Container networkC von networkA und networkB isoliert.
Beispiel 4): Komplexeres Beispiel
Als Annahme wird folgender Serviceverbund herangezogen:
- Reverseproxy
- Funktion: Übernimmt Caching und Verschlüsselung, nach außen Sichtbar, z.B.: nginx
- Kommunikation: Anwendung
- Anwendung
- Funktion: Liefert Webseite zurück und dient als API, z.B.: vuejs + express
- Kommunikation: Reverseproxy und Datenbank
- Datenbank
- Funktion: Liefert Daten für die Anwendung, z.B.: MySQL
- Kommunikation: Anwendung
Netzwerke erstellen
Reverseproxy ---> Netzwerk tier1 <--- Anwendung ---> Netzwerk tier2 <--- Datenbank
docker network create tier1
docker network create tier2
Container starten
#Reverseproxy
docker run --name reverseproxy --network tier1 --hostname reverseproxy --rm -d networking_example2:1.0
#App
docker run --name app --network tier1 --hostname app --rm -d networking_example2:1.0
#Netzwerk muss mit Container verbunden werden
docker network connect tier2 app
#Db
docker run --name db --network tier2 --hostname db --rm -d networking_example2:1.0
Terminal 1 - Reverseproxy
#Bash starten
docker exec -it reverseproxy bash
#Erreichbarkeit
ping app #ok
ping db #not reachable
Terminal 2 - Application
#Bash starten
docker exec -it app bash
#Erreichbarkeit
ping reverseproxy #ok
ping db #ok
Terminal 3 - Database
#Bash starten
docker exec -it db bash
#Erreichbarkeit
ping reverseproxy #not ok
ping app #ok
Beispiel 5): Host Network
Beim Host Netzwerk entfällt die Netzwerkisolierung. dies kann für einen Loadbalancer oder Reverseproxy Sinn machen und die Konfiguration erleichtern.
Ein gutes Beispiel stellt ein Reverseproxy dar. Der Proxy leitet Daten an verschiedene jeweils voneinander (bezogen auf die Netzwerkebene) isolierte Container weiter, welche jeweils einen anderen Port exponieren. Wird ein Bridge Network für den Proxy verwendet, so muss jeder entsprechende Container teil dieses Netzwerks sein. Somit können auch alle Container untereinander kommunizieren, was unter Umständen nicht gewünscht ist. Dies würde sich dann so verhalten wie beim default Bridge Netzwerk.
Bei Verwendung des Host Netzwerks, muss jeder Container lediglich den entsprechenden Port zum Host exponieren. Der Reverseproxy kann somit automatisch die Daten an die Ports weiterleiten.
Container starten
#Der Host Parameter kann weggelassen werden, dieser wird vom Host übernommen
#Etwaige Port Weiterleitungen entfallen, bzw. werden nicht berücksichtigt
docker run --name networkingHost --network host --rm -d networking_example2:1.0
Prüfen der Verbindung
curl http://localhost:5000
<html><h1>Welcome</h1></html>