Single-host network and DNS

November 15, 2021 - Reading time: 6 minutes

Docker creates three networks by default:

test@localhost: sudo docker network ls 
NETWORK ID     NAME      DRIVER    SCOPE
87b1b48fc040   bridge    bridge    local
bc4e37844d7a   host      host      local
6a689a237adc   none      null      local

All containers are attached to bridge for inter-container connectivity. The host networks is used to place containers on the host namespace. Possible scopes are local , global (be part of a swarm, but don't route) and swarm.

Each container has a loopback int and a private interface that's attached to the docker0 virtual interface.

Create a new bridge network with a different subnet, make it attachable so that containers can be attached/removed at any point:

test@localhost: sudo docker network create --driver bridge --label test=first --attachable --scope local --subnet 10.55.11.0/24 --ip-range 10.55.11.128/25 mynetwork
bf0d64f6d3e10f04b87ae5d33606e0c34302b8fbcde8d6851612062e2bc02ccf

Networks can be added to containers:

test@localhost: sudo docker run --interactive --tty --network mynetwork --name test alpine sh
[...]
/ # ip -f inet -4 -o addr
1: lo    inet 127.0.0.1/8 scope host lo\       valid_lft forever preferred_lft forever
61: eth0    inet 10.55.11.129/24 brd 10.55.11.255 scope global eth0\       valid_lft forever preferred_lft forever

Create a new network, and connect our existing container:

test@localhost: sudo docker network create --driver bridge --label test=first --attachable --scope local --subnet 10.66.11.0/24 --ip-range 10.66.11.128/25 mynetwork2
71b6284bdc851e5a6f4d3296952ecaa93428f18935b946385017594f4948f6bb
test@localhost: sudo docker network connect mynetwork2 test 
test@localhost: sudo docker attach test
/ # ip -f inet -4 -o addr
1: lo    inet 127.0.0.1/8 scope host lo\       valid_lft forever preferred_lft forever
61: eth0    inet 10.55.11.129/24 brd 10.55.11.255 scope global eth0\       valid_lft forever preferred_lft forever
64: eth1    inet 10.66.11.129/24 brd 10.66.11.255 scope global eth1\       valid_lft forever preferred_lft forever

If I now create another container, and attach it to mynetwork2, I can do a reverse DNS lookup to get the hostname:

test@localhost: sudo docker attach test
/ # dig -x 10.66.11.130 +short
test2.mynetwork2.
test@localhost: sudo docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED          STATUS          PORTS     NAMES
9829476f60f8   alpine    "sh"      8 minutes ago    Up 8 minutes              test2
dd071d4ee496   alpine    "sh"      16 minutes ago   Up 16 minutes             test

Swarm

When working with multiple node in a swam, we need to use the overlay driver to create a logical switch that expands to all nodes in the cluster. This allows inter-communication between containers in different nodes.

Host network

The container and the host share the same network namespace:

test@localhost: sudo docker run --interactive --tty --network host --name testhost alpine /bin/sh
/ # ip -f inet -4 -o addr
1: lo    inet 127.0.0.1/8 scope host lo\       valid_lft forever preferred_lft forever
2: ens33    inet 192.168.0.12/24 brd 192.168.0.255 scope global dynamic ens33\       valid_lft 75444sec preferred_lft 75444sec
3: docker0    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0\       valid_lft forever preferred_lft forever
60: br-bf0d64f6d3e1    inet 10.55.11.128/24 brd 10.55.11.255 scope global br-bf0d64f6d3e1\       valid_lft forever preferred_lft forever
63: br-71b6284bdc85    inet 10.66.11.128/24 brd 10.66.11.255 scope global br-71b6284bdc85\       valid_lft forever preferred_lft forever

NodePort publishing

Used to provide in-bound connectivity to the container on a specific port.
The --publish list includes tuples of host:container ports. It can only be specified during creation: create or run
-p 8080 -> forwards random port in the host to 8080 in the container
-p 8080:8080/udp -> forwards UDP:8080 in the host to the same in the container
All the published ports can be listed with:

test@localhost: sudo docker run --detach --name list01 --publish 8080 alpine sleep 1d
6451adc9b7daccc6df93f0c0cb55d571b4a682b11194bbbfc5f3e3033232cb07
test@localhost: sudo docker run --detach --name list02 --publish 8080:8080 alpine sleep 1d
732cb05042ee2d2e037802ab1fce7ee53a9afa75b611a2eea214bcbca21001f1
test@localhost: sudo docker port list01
8080/tcp -> 0.0.0.0:49153
8080/tcp -> :::49153
test@localhost: sudo docker port list02
8080/tcp -> 0.0.0.0:8080
8080/tcp -> :::8080

DNS

Names assigned to containers via --name or --hostname can be used by other containers in the same network to resolve the IP Address.

test@localhost: sudo docker run --interactive --tty --hostname myhostname.cool.uk --network mynetwork --name anyname alpine sh 
/ # cat /etc/hosts 
[...]
10.55.11.130    myhostname.cool.uk myhostname
test@localhost: sudo docker attach test
/ # dig +short myhostname.cool.uk 
10.55.11.130
/ # dig +short anyname.mynetwork
10.55.11.130

The container settings can be overridden with --dns and --dns-search and add static hosts with --add-host