Skip to main content

Command Palette

Search for a command to run...

Understanding Docker Networks: A Beginner's Tutorial

Updated
6 min read
Understanding Docker Networks: A Beginner's Tutorial
G

I am student currently pursuing my Bachelor's in computer science. I have a keen interest in DevOps and LINUX related technologies

CONTENTS:

  • Introduction

  • Building our custom image

  • Creating a custom network

  • Connecting two custom networks

Introduction

Firstly we need to be a little familiar with the docker networks. Docker connects freshly created containers to a default network called bridge. This bridge network acts as a bridge between host and containers, this allows communication between containers and with the host as well. To verify this let's spin up a simple container.

docker run -d --name s1 httpd
docker inspect s1

you will see something like this

inspect output for s1

You can see that the network type is a bridge, there is an IP address 172.17.0.2 which is your container's internal IP address and a gateway 172.17.0.1. This is the common gateway for all the containers attached to the default bridge network. This gateway allows for communications outside the network. To understand it more effectively we need to equip the httpd image with some Linux networking tools.

Building our custom image

FROM httpd
RUN apt-get update &&\
    apt-get install -y iputils-ping &&\
    apt-get install -y inetutils-traceroute &&\
    apt-get install -y iproute2 &&\
    apt-get install -y curl telnet dnsutils vim

This file will install tools like ping,traceroute,ip route,curl ,telnet,DNS utilities and vim.

Copy this code into a docker file and build an image, we will be using nhttpd as the name of our new image.

Run two containers by name s1 and s2 and exec into it

docker build . -t nhttpd 
docker run  --name s1  -d nhttpd
docker run --name s2 -d nhttpd
docker exec -it s1 /bin/bash

Notice that we did not publish any ports to the host, try pinging google.com now that you are inside the container.

ping google.com

You will see something like this

How are we getting a response back? Well, the gateway makes this possible. When you ping google the packets are sent to the gateway which is connected to an interface that opens to the host connected to the internet and that is how we can reach Google from inside our container.

Try pinging the container s2 using its hostname

ping s2

We did not get a response back. Why is that? well let's try nslookup on s2

nslookup s2

nslookup
nslookup is a program to query Internet domain name servers. nslookup has two modes: interactive and non-interactive. Interactive mode allows the user to query name servers for information about various hosts and domains or to print a list of hosts in a domain. Non-interactive mode prints just the name and requested information for a host or domain.

Notice the server address this is not the container's subnet. The networking intricacies within Docker often lead to packets being directed to a gateway connected to a host-accessible interface, rather than the intended container subnet. This scenario can result in attempts to access resources outside the network through the host's DNS server. In the upcoming section on "Creating a Custom Network," we will explore a solution to address this issue and gain a deeper understanding of how to configure Docker networks to ensure efficient communication within containers while resolving external resource requests accurately.

Here is something try pinging container s2 from container s1 using its ip address.

ping 172.17.0.3

So the hostname doesn't work but the IP address does.

This is also concerning. A container can ping another container on the same network. This explains the need for creating our network as any container on the same network can communicate with our container.

Creating a custom network

Create a network named backend and connect our containers s1 and s2 to it using the below commands.

docker network create backend --subnet 10.0.0.0/24
docker network connect backend s1
docker network connect backend s2

Also, we need to disconnect these two from the default network to isolate them.

docker network disconnect bridge s1
docker network disconnect bridge s2

# exec inside s1
#you can inspect network to get more information using docker network inspect backend
docker exec -it s1 /bin/bash

Now let us try again to reach s2 without using its ip

nslookup s2

Notice the difference, what happens is that Now within this isolated network, we have our DNS set up — a great step forward! However, should you wish to restrict internet access, you can achieve this by creating the network using the --internal option.

But what if you want this isolated network to establish communication with another network, perhaps named "frontend"? In the next section, we'll explore how to facilitate this inter-network communication while maintaining the desired level of isolation.

Connecting two custom networks

This is where things get fun. First, create another container named gateway and connect to another network named frontend.

docker network create frontend --subnet 10.0.1.0/24

docker run --name gw -d nhttpd

# connecting container to networks

docker network connect frontend gw
docker network connect backend gw

What we need to do is to add an IP route inside the containers s1 and s2 defining the rule for transferring packets. To do that we need to grant NET_ADMIN capabilities to these containers. You can remove these containers and create new ones with --cap-add=NET_ADMIN.

--cap-add=NET_ADMIN
NET_ADMIN grants network administrator capabilities to the container.

Remove the containers s1 and s2 and create new containers s1 and s2.

docker rm s1 s2 -f 

#creating new containers
docker run --name s1 -d --cap-add=NET_ADMIN nhttpd
docker run --name s2 -d --cap-add=NET_ADMIN nhttpd

#attach them to backend and frontend respectively 

docker network connect backend s1
docker network connect frontend s2

Now we need to add the rule to both s1 and s2. Exec into s1 and add

docker exec -it s1 /bin/bash
ip route add 10.0.1.0/24 via 10.0.0.4  #10.0.0.4 is ip of gw in backend

Similarly, add this to s2

docker exec -it s2 /bin/bash
ip route add 10.0.0.0/24 via 10.0.1.2 #10.0.0.2 is ip of gw in frontend
ip route
ip route is used to manipulate entries in the kernel routing tables.

You can check the IP addresses of containers in a network using inspect. Make sure that you enter the correct IP address while adding the route.

docker network inspect backend
docker network inspect frontend

Try tracing the route of packets from inside s1 and s2.

docker exec -it s2 /bin/bash
traceroute 10.0.0.2

traceroute
traceroute tracks the route packets taken from an IP network on their way to a given host. It utilizes the IP protocol's time to live (TTL) field and attempts to elicit an ICMP TIME_EXCEEDED response from each gateway along the path to the host.

As you can see the packet first went to 10.0.1.2 which is our container gw and then to its destination 10.0.0.2 which is s1.

similarly,

docker exec -it s1 /bin/bash
traceroute 10.0.1.3

Here the gw container is at address 10.0.0.4

This concludes this article on playing with docker networks. Docker networks can be a little tricky but are fun to experiment with, if you have questions feel free to drop them in the comment box and I will see you in the next article.

S

Helpful