sehaj/learn
Docker/05 Networking

05.02 · with code · 12 min

User-defined bridges and DNS

Create your own networks so containers find each other by name, and use more than one to keep things that shouldn't talk apart.

The core idea

A user-defined bridge is a bridge network you create with docker network create. It works like the default one, plus two things that matter: containers on it can find each other by name, through DNS built into Docker, and it's isolated from containers on other networks.

Names, not IPs

❯terminal
$ docker network create appnet
$ docker run -d --name web1 --network appnet nginx:alpine
$ docker run --rm --network appnet alpine sh -c 'cat /etc/resolv.conf; nslookup web1; wget -qO- http://web1'
nameserver 127.0.0.11
options ndots:0
Name: web1
Address: 172.20.0.2
<title>Welcome to nginx!</title>

Output trimmed. Compare resolv.conf with the default bridge's (05.01 How container networking works): on a user-defined network, every container asks 127.0.0.11, Docker's embedded DNS server. It answers with the current IP of any container on the same network, by name, and forwards everything else to the normal resolver.

Recreate web1 and it may get a new IP, but http://web1 keeps working.

Aliases

A container can answer to extra names with --network-alias. Give several containers the same alias and DNS returns all of them:

❯terminal
$ docker run -d --name api1 --network appnet --network-alias api alpine sleep 300
$ docker run -d --name api2 --network appnet --network-alias api alpine sleep 300
$ docker run --rm --network appnet alpine nslookup api
Address: 172.20.0.4
Address: 172.20.0.3

Clients pick one of the addresses, which gives you crude load-spreading. It's a DNS trick, not a load balancer: there are no health checks, and clients often cache the answer.

Isolation between networks

Containers on different user-defined networks can't reach each other, not even by IP:

❯terminal
$ docker network create frontend
$ docker network create backend
$ docker run -d --name dbx --network backend nginx:alpine
$ docker run --rm --network frontend alpine wget -qO- -T 3 http://dbx
wget: bad address 'dbx'
$ docker run --rm --network frontend alpine wget -qO- -T 3 http://172.22.0.2
wget: download timed out

The name doesn't resolve, and the IP isn't routable from the other network. That's the basis of a simple, useful security layout: a public-facing proxy on one network, the database on another, and only the app on both.

One container, several networks

docker network connect attaches a running container to another network. It gets a second interface:

❯terminal
$ docker run -d --name bridgebox --network frontend alpine sleep 300
$ docker network connect backend bridgebox
$ docker exec bridgebox ip -4 addr | grep inet
inet 127.0.0.1/8 scope host lo
inet 172.21.0.2/16 brd 172.21.255.255 scope global eth0
inet 172.22.0.3/16 brd 172.22.255.255 scope global eth1
$ docker exec bridgebox wget -qO- http://dbx | grep -o '<title>.*</title>'
<title>Welcome to nginx!</title>

eth0 is on frontend, eth1 on backend, and the container can reach both sides. docker network disconnect removes it again.

The layout project step 4 uses
notes-frontendpublic side
nginx (publishes :8080)
notes API
notes-backendprivate side
notes API
postgres
redis
Only the API is on both. Nginx can't reach the database or Redis even if it's compromised.
Predict first

Your API is on network backend. You add nginx on network frontend and point it at http://api:3000. Nginx logs 'host not found'. What's the smallest fix?

Commit to an answer before you read on.
CheckpointBuild a two-network layout

Create frontend and backend. Put an nginx on backend named secret. From a container on frontend, show you can't reach it. Then attach that container to backend as well and show you can. Clean up with docker network rm (it fails while containers are attached).

STUCK? ▸

Names don't resolve: check both containers are on the same network with docker network inspect NAME, which lists every attached container. Remember the default bridge never resolves names.

Recap

Interview questions

JuniorfreqMust-knowConcept

How do containers discover each other in Docker?

MidfreqGood to knowDesign

How would you stop a public-facing container from reaching your database?

Report a mistakeEdit this page