Die Standard Netzwerke
Bei allen docker Installationen wird das Netzwerk Interface docker0
erstellt, welches ein bridge
Netzwerk ist und sich in der Regel an das erste Netzwerk-Interface und das loopback
Interface bindet.
Dieses verwendet ein /16 Netz für die Container.
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:3d:cc:65:07 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:3dff:fecc:6507/64 scope link
valid_lft forever preferred_lft forever
Eine Übersicht über die vorhandenen Netzwerke erhält man mit docker network ls
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
d3ba53468648 bridge bridge local
4b043328757f host host local
6a16d77c03b6 none null local
bridge
Die bridge
erstellt ein eigenes privates Netzwerk auf dem host um es Containern zu ermöglichen über dieses Netzwerk zu kommunizieren.
Mit Hilfe der im letzten Teil der Tutorial Reihe vorgestellten --expose
Option ist auch ein Zugriff auf die Container außerhalb des privaten Netzwerkes möglich.
Bei der Erstellung eines solchen Netzwerkes kümmert sich docker im Hintergrund um das Anlegen der notwendigen Linux bridges, internen Interfaces, iptables Regeln und Host Routen.
Weitere Argumente für das Anlegen eines benutzerdefinierten bridge
Netzwerkes findet man hier: Use bridge networks
host
Laut Dokumentation erlaubt das host
Netzwerk, dass ein Container sich den Netzwerk-Stack mit dem Host teilt. Dies soll eine bessere Netzwerk Performance bringen.
Wenn man also einen Container mit Nginx und dem host
Netzwerk startet, ist der Nginx auf dem Host auf Port 80 erreichbar.
docker run --rm -d --network host --name mein_nginx nginx
$ curl -I localhost:80
HTTP/1.1 200 OK
Server: nginx/1.17.0
Date: Thu, 13 Jun 2019 18:42:53 GMT
...
none
Hierbei hat ein Container keinerlei externe ROuten und es ist lediglich das loopback
Device aktiv.
Anmerkung:
Die Einzelheiten jedes dieser Netzwerke in der Liste kann man sich mit docker network inspect <NETWORK ID/NAME>
anschauen.
Beispiel:
$ docker network inspect host
[
{
"Name": "host",
"Id": "4b043328757f12838d47535cd6660c466a41c6fb6e36dfc8c5624e914764e786",
"Created": "2019-06-11T14:08:25.862917584Z",
"Scope": "local",
"Driver": "host",
...
docker network …
Die entsprechende docker-Dokumentation findet sich hier: Docker container networking
Sofern nichts extra angegeben wird, wird jeder neu erstellte Container automatisch zum bridge
Netzwerk hinzugefügt.
Um zu schauen welches Netzwerk ein Container verwendet, sucht man per grep
in der entsprechenden Ausgabe des Befehls docker container inspect <CONTAINER ID/Containername>
:
"Networks": {
"bridge": {
"IPAMConfig": null,
...
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.3",
...
Ein Container mit bridge
Netzwerk hat auch automatisch eine Route ins Internet.
Zum testen erstelle ich mir einen Container aus dem aktuellsten CentOS Image und lasse dort beim Start eine bash
starten.
docker run -d -it --name centos centos bash
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b44b6b38b319 centos "bash" 3 seconds ago Up 3 seconds centos
Nun können wir über die bash
im eben erstellten Container versuchen eine externe Domain aufzurufen:
$ docker attach centos
[root@b44b6b38b319 /]# ping joinmastodon.org
PING joinmastodon.org (104.18.41.107) 56(84) bytes of data.
64 bytes from 104.18.41.107 (104.18.41.107): icmp_seq=1 ttl=42 time=10.5 ms
...
Des weiteren kann das Host System auch den Container üer seine, von docker vergebene, IP erreicht werden. Hierzu sucht man sich wieder per inspect und grep
die entsprechende IP-Adresse des Containers und pingt diesen an:
$ ping 172.17.0.4
PING 172.17.0.4 (172.17.0.4) 56(84) bytes of data.
64 bytes from 172.17.0.4: icmp_seq=1 ttl=64 time=0.078 ms
64 bytes from 172.17.0.4: icmp_seq=2 ttl=64 time=0.054 ms
Welche Befehle der docker network
Befehl kennt, erfährt man mit docker network --help
$ docker network --help
Usage: docker network COMMAND
Manage networks
Commands:
connect Connect a container to a network
create Create a network
disconnect Disconnect a container from a network
inspect Display detailed information on one or more networks
ls List networks
prune Remove all unused networks
rm Remove one or more networks
Run 'docker network COMMAND --help' for more information on a command.
rm
Mit docker network rm <NETWORK ID/NAME>
lassen Netzwerke auch wieder entfernen.
Sollte das zu löschende Netzwerk noch von einem Container aktiv genutzt werden, so gibt es eine entsprechenden Warnung:
$ docker network rm br0
Error response from daemon: error while removing network: network br0 id c6ea95f50f39e381968968a4a01e35da21f72b030fc3d12680aa4e07c348771d has active endpoints
prune
Das docker network prune
Kommando löscht alle Netzwerke, welche von keinem Container verwendet werden. Hierbei sollte man immer Vorsicht walten lassen, da im Vorfeld nicht ersichtlich ist welche Netzwerke gelöscht werden.
$ docker network prune
WARNING! This will remove all networks not used by at least one container.
Are you sure you want to continue? [y/N] y
Deleted Networks:
newbridge00
create
Mit dem Befehl docker network create <Netzwerkname>
kann ein weiteres Netzwerk hinzufügen. Gibt man keine weiteren Optionen an wird ein weiteres bridge
Netzwerk erzeugt.
Dokumentaion: docs.docker.com
docker network create newbridge00
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
...
a341c965b43d newbridge00 bridge local
...
$ docker network inspect newbridge00
[
{
"Name": "newbridge00",
"Id": "a341c965b43da2eac324cfa8fbc76b79d314a6bbef18ebc3ed88a2bbf23aa661",
"Created": "2019-06-13T17:31:29.381566066Z",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "172.18.0.0/16",
"Gateway": "172.18.0.1"
...
Nach der Erstellung findet sich auf dem Host ein entsprechendes bridge
Interface, welches den Namen br-<NETWORK ID der Bridge>
hat.
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
c6ea95f50f39 br0 bridge local
...
$ ip a | grep c6ea95f50f39
12: br-c6ea95f50f39: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
inet 172.28.5.254/16 brd 172.28.255.255 scope global br-c6ea95f50f39
Mit der Möglichkeit eigene (benutzerdefinierte) bridge
Netzwerke zu erstellen bietet sich die Möglichhkeit Container (netzwerktechnisch) in Gruppen anzuordnen, wo die einzelnen Container nur mit anderen Containern im gleichen bridge
Netzwerk kommunizieren können aber nicht mit Containern in anderen bridge
Netzwerken.
Im folgenden Beispiel erstelle ich ein neues bridge
Netzwerk mit Namen br0
und erstelle 2 Container, welche ich diesem neuen Netzwerk mit Hilfe der --network
Option zuordne.
$ docker network create --subnet=172.28.0.0/16 --ip-range=172.28.5.0/24 --gateway=172.28.5.254 br0
Die möglichen Optionen erfährt man auch wieder mit docker network create --help
.
Anmerkung: Bei der Vergabe benutzerdefinierter IPadressen und IP-Ranges sollte man immer darauf achten nur private IP-Adressen zu verwenden.
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
c6ea95f50f39 br0 bridge local
docker container run -d -p 8081:8080 --name httpd_centos --network br0 centos/httpd-24-centos7
docker container run -d -p 8080:80 --name nginx --network br0 nginx
docker inspect nginx | grep -i ipaddress
"IPAddress": "172.28.5.1",
$ docker container inspect httpd_centos | grep Networks -A 1
"Networks": {
"br0": {
Die beiden eben erstellten Container nginx
und httpd_centos
können nun untereinander kommunizieren…
$ docker exec -it httpd_centos /bin/bash
bash-4.2$ curl -I nginx
HTTP/1.1 200 OK
Server: nginx/1.17.0
...
bash-4.2$ ping nginx
PING nginx (172.28.5.1) 56(84) bytes of data.
64 bytes from nginx.br0 (172.28.5.1): icmp_seq=1 ttl=64 time=0.054 ms
...
Und auch das Hostsystem kann mit den Containern im bridge
Netzwerk br0
problemlos kommunizieren.
Mit den Optionen --ip
in Kombination mit --network
kann man einem Container bei der Erstellung auch eine benutzerdefinierte IP-Adresse zuordnen, man sollte aber darauf achten, dass diese auch in der IP-Range des entsprechenden bridge
Netzwerkes ist.
connect
Möchte man einen bestehenden Container einem weiteren docker-Netzwerk zuordnen verwendet man den Befehl docker network connect <docker-Netzwerk> <CONTAINER ID/Containername>
Hierzu legen wir uns erst wieder einen neuen Container per docker run -d --name nginx02 nginx
an und schauen welchem docker-Netzwerk dieser zugeordnet ist:
$ docker container inspect nginx02 | grep Networks -A 1
"Networks": {
"bridge": {
Nun fügen wir diesen Container dem neuen docker-Netzwerk per docker network connect br0 nginx02
zu und prüfen dann erneut:
$ docker container inspect nginx02
...
"Networks": {
"br0": {
...
bridge": {
...
Damit ist der Container über 2 verschiedenen IPadressen bzw. docker-Netzwerke ansprechbar.
disconnect
Möchte man einen Container wieder aus einem bestimmten docker-Netzwerk entfernen verwendet man den Befehl docker network disconnect <docker-Netzwerk> <CONTAINER ID/Containername>
Beispiel: docker network disconnect br0 nginx02