Zodra een docker-container wordt gestart zal de Docker Engine hier een netwerk interface aan koppelen en er een IP adres aan ‘binden’. Tevens wordt een default gateway verwijzing gemaakt en DNS en routing tables. Standaard kunnen alle containers op de host met elkaar communiceren. Soms is dat niet gewenst en kan er een custom-network gebruikt worden of door gebruik te maken van een network provider plugin.
Network providers maken gebruik van drivers en voor docker wordt dat gedaan met de ‘--net=
‘ parameter, bijvoorbeeld:
$ docker run --rm --net=host busybox ip addr
Er zijn voor docker 5 network types beschikbaar:
- Host Networking: the docker container gebruikt hetzelfde netwerk en IP adres als de host waarop het draait.
- Bridge Networking: de container maakt gebruik van een private network op de host en kan communiceren met alle containers op de host die hier ook gebruik van maken. Communicatie vanuit andere netwerk(en) gaat via NAT. Dit is tevens de default zla de –net optie niet wordt meegegeven.
- Custom Bridge Networking: Gelijk aan Bridge Networking echter met een specifieke network interface op de host.
- Container-defined Networking: Een container kan een netwerk voor een andere container delen.
- No Networking: containers zonder netwerk interface.
Host Networking
Op een host met hierop docker geïnstalleerd, voer de volgende commando’s uit:
$ ip addr
$ docker run --rm -it --net=host busybox ip addr
De output van beide commando’s zal hetzelfde zijn, de docker container maakt immers gebruik van de shared network adapters van de host waarop het draait.
1: lo: mtu 65536 qdisc noqueue qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever 2: eth0: mtu 1500 qdisc mq qlen 1000 link/ether dc:a6:32:f4:f2:a2 brd ff:ff:ff:ff:ff:ff inet 192.168.1.51/24 brd 192.168.1.255 scope global dynamic eth0 valid_lft 61134sec preferred_lft 61134sec inet6 fe80::dea6:32ff:fef4:f2a2/64 scope link valid_lft forever preferred_lft forever 3: wlan0: mtu 1500 qdisc fq_codel qlen 1000 link/ether dc:a6:32:f4:f2:a3 brd ff:ff:ff:ff:ff:ff 4: docker0: mtu 1500 qdisc noqueue link/ether 02:42:28:27:aa:3f 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:28ff:fe27:aa3f/64 scope link valid_lft forever preferred_lft forever
Bridge Networking
Indien hetzelfde docker commando wordt gegeven zonder de --net
optie, zal gebruik gemaakt worden van de docker0 bridge.
docker run --rm -it busybox /bin/sh $ ip addr
1: lo: mtu 65536 qdisc noqueue qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever 6: eth0@if33: mtu 1500 qdisc noqueue link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0 valid_lft forever preferred_lft forever
Op de host zelf zal een interface gemaakt worden voor de container:
$ ip addr | grep veth 7: veth1718da2@if46: mtu 1500 qdisc noqueue master docker0 state UP group default link/ether ae:eb:61:f3:c1:e5 brd ff:ff:ff:ff:ff:ff link-netnsid 1 inet6 fe80::aceb:61ff:fef3:c1e5/64 scope link valid_lft forever preferred_lft forever
Ook al maakt de docker container gebruik van een IP adres van het bridge network, services die in de container draaien zijn niet beschikbaar buiten de host waar de container op draait. Om dat wel beschikbaar te maken moet een de Docker Engine de instructie gegeven worden om een bepaalde TCP-port door te sturen van de host naar de container. Bijvoorbeeld een webserver dir op port 80 draait in een container en die bereikbaar moet zijn vanaf de host op port 8080:
$ docker run --name nginx --rm -p 8080:80 -d nginx
$ docker inspect nginx --format='{{json .NetworkSettings.IPAddress}}' "172.17.0.2"
Docker Daemon maakt nu een rule aan in Netfilter dat outbound packages het IP adres van de host meegeeft en inbound packages worden doorgestuurd naar de docker container.
$ sudo iptables -L -t nat -v
Chain PREROUTING (policy ACCEPT 141 packets, 11704 bytes) pkts bytes target prot opt in out source destination 344K 26M DOCKER all -- any any anywhere anywhere ADDRTYPE match dst-type LOCAL Chain INPUT (policy ACCEPT 141 packets, 11704 bytes) pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 147 packets, 9629 bytes) pkts bytes target prot opt in out source destination 47 2820 DOCKER all -- any any anywhere !localhost/8 ADDRTYPE match dst-type LOCAL Chain POSTROUTING (policy ACCEPT 147 packets, 9629 bytes) pkts bytes target prot opt in out source destination 0 0 MASQUERADE all -- any !br-844b6c606eb4 172.18.0.0/16 anywhere 0 0 MASQUERADE all -- any !docker0 172.17.0.0/16 anywhere 0 0 MASQUERADE tcp -- any any 172.17.0.2 172.17.0.2 tcp dpt:http Chain DOCKER (2 references) pkts bytes target prot opt in out source destination 0 0 RETURN all -- docker0 any anywhere anywhere 0 0 DNAT tcp -- !docker0 any anywhere anywhere tcp dpt:http-alt to:172.17.0.2:80
Custom-Bridge Networking
Indien er geen noodzaak is om de default bridge te gebruiken, maak een custom bridge network op de host.
$ docker network create customnetwork $ docker run -it --rm -d --name=container-1 --net=customnetwork busybox /bin/sh $ docker run -it --rm -d --name=container-2 --net=customnetwork busybox /bin/sh
Container-defined Networking
De volgende commando’s maken twee containers aan die een gedeeld network interface gebruiken. Dit is feitelijk hoe Kubernetes ook werkt met pods.
$ docker run -it --rm -d --name=container-1 busybox /bin/sh $ docker run -it --rm -d --name=container-2 --net=container:container-1 busybox /bin/sh
No Network
In die gevallen waarbij geen netwerk voor de container nodig is.
$ docker run --rm --net=none --name busybox busybox ip addr 1: lo: mtu 65536 qdisc noqueue qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever