Basics of Docker Networking

I have been wanting to learn some basic networking in Docker and what better way than by building a super simple image from a custom template and inspect the communication between two containers!

The image will just be based on httpd with some additional tooling.

# base image on Apache HTTP server
FROM httpd

# install additional tooling we will use to debug a bit with
RUN apt-get update && apt-get install -y \
    iputils-ping \
    inetutils-traceroute \
    iproute2 \
    curl \
    telnet \
    dnsutils \
    vim

Build it!

docker build --tag httd .

The value passed to --tag/-t is actually the name value, the image will be tagged with the default which is always :latest, resulting in httd:latest.

Beautiful. With this very fresh and very cool image we can start two containers.

docker run --detach --name one dhttp
docker run --detach --name other dhttp

Nothing fancy and mostly default values all around. Inspecting the NetworkSettings prop for the container of one feels like a good place to start.

docker container inspect one | jq '.[].NetworkSettings'

I love using jq for inspecting or editing JSON strings. If you haven’t heard about it before then check it out!

While the output from inspect is pretty lengthy, there is not a lot of scary looking information in there… Of course, some things are going right above my head but I will just ignore them for now.

I do find some things in the Networks object interesting though.

docker container inspect one | jq '
.[].NetworkSettings.Networks[]
| { Aliases, IPAddress, Gateway }
'

Aliases in particular stuck out to me so I looked it up.

--alias option can be used to resolve the container by another name in the network being connected to.

So aliases are basically host names that will be resolved by Docker within a network. Most people, myself included, have surely used aliases before when using Docker Compose, but getting some deeper knowledge about things is always rewarding. Like seeing these values in the actual container configuration.

Focusing on the Networks object one can see that one (heh) belongs to a single network, bridge. Let’s see how this looks from the perspective of the network by inspecting bridge.

docker inspect bridge | jq '.[] | { Containers, Config: .IPAM.Config }'

From the output we can identify our container IP addresses.

Cool, if we have the IP addresses we can curl them! — You, maybe

Let us put that theory to the test.

curl --connect-timeout 3 <ONE_IP_ADDRESS>

Did it time out? I bet it did. The reason is that containers lives only within the bridge network which in turn lives inside of Docker Engine running on our computer. How in the world would it be able to know where to route requests heading to <SERVER1_IP_ADDRESS>?

Happy coding!