Docker Networking
Docker is a powerful tool for containerising applications, but to truly leverage its potential, it’s important to have a solid understanding of Docker Networking. With Docker Networking, developers can create sophisticated network architectures that enable their containers to communicate seamlessly and securely.
In this blog, we’ll dive into the world of Docker Networking, how to create networks in docker and how to configure them effectively. We’ll look at how to manage container IP addresses, how to set up communication between containers, and how to secure your Docker network.
Let’s start, Run httpd based container
Run container based on the httpd image, you can use the following command in your terminal or command prompt:
docker run -d -p 80:80 httpd # in host machine
docker ps # in host machine
Once your container is running successfully, you can access the web server on port 80. To verify that the server is up and running, you can use either the curl command or your web browser.
To use the curl command, open a new terminal or command prompt and enter the following command:
curl http://localhost # in host machine
This will send an HTTP GET request to the server running in your container, and return the response from the server.
Alternatively, you can open your web browser and navigate to http://localhost
or http://<host-machine-IP-address>
. If the server is up and running, you should see the default Apache HTTP Server page.
If everything is working fine, it means that we have successfully created a container within a network. Docker Networking allows containers to communicate with each other and with the outside world, enabling complex network topologies that are flexible, scalable, and secure.
By default, Docker creates a bridge network for each Docker installation. When we run a container without specifying a network, Docker automatically connects it to the bridge network. This allows the container to communicate with other containers on the same network and with the host machine.
Let’s inspect container for more details,
docker inspect <container-id> # in host machine
docker inspect f4a # in host machine
Here we can see the details of networks in which we created our container. Container can have more then one network. We can see our container’s default network bridge, IP address and gateway.
We can also inspect network using following command,
docker inspect network <network-name> # in host machine
docker inspect network bridge # in host machine
This will display information about the containers connected to the default bridge network, including their IP addresses and gateway.
Here our container ip address is 172.17.0.2 , Now try to curl container ip address in host machine
curl http://172.17.0.2 # in host machine
This is not working? why my host machine is not able to reach my container? Because the container is running in a virtual machine with its own network. In this case, our host machine does not have direct access to the container’s network, which can make it difficult to communicate with the container. To access Docker container from your host machine, we have to find a way to connect to the container’s network.
However, the Docker container can still access the internet through the host machine’s network. This allows the container to download software packages, access web services, and perform other network-related tasks.
if you’re running Docker on Linux, you may not need to worry about this issue. On Linux, Docker runs natively on the host machine with the same network, which means that you can access the container directly from your host machine without any additional setup.
Let’s build our own image. before that delete container for clear understanding.
docker stop f4a # in host machine
docker rm f4a # in host machine
let’s create 2 container with bellow Dockerfile for better understanding of the network,
FROM httpd
RUN apt-get update
RUN apt-get install -y iputils-ping
RUN apt-get install -y inetutils-traceroute
RUN apt-get install -y iproute2
RUN apt-get install -y curl telnet dnsutils vim
build the image newhttpd,
docker build . -t newhttpd # in host machine
Now create containers s1 and s2 based on newhttpd,
docker run --name s1 -d newhttpd # in host machine
docker run --name s2 -d newhttpd # in host machine
docker ps # in host machine
We didn’t expose any port so we can not access web servers. let’s check the bridge network in which we can see containers details.
docker inspect network bridge # in host machine
Let’s bash into s1 and ping google.com,
docker exec -it s1 bash # in host machine
ping google.com # in s1
We can ping google.com from the container that because of default getway.
docker host is the VM which is in our host machine. So when ever s1 do ping for google.com then the it use dns server of docker host machine.
We can see that ip of our dns server is 192.168.65.7 which is not in same network as our container’s network. Now let’s try to do nslookup on s1 or hostname. we couldn’t find the domain. This happen because our container’s doing dns query to 192.168.65.7 and that server don’t know about that hostname. But we can ping with ip address.
In bridge network container can talk to each other but with only ip address let’s fix that by creating custom network.
docker network create backend --subnet 10.0.0.0/24 # in host machine
docker network connect backend s1 # connect s1 to network backend
docker network connect backend s2 # connect s2 to network backend
docker inspect network backend
We can see that our container is in two network(bridge & backend) by inspecting the server,
docker inspect s1 # in host machine
let’s remove s1 and s2 from bridge network,
docker network disconnect bridge s1 # in host machine
docker network disconnect bridge s2
Now bash in s1 and nslookup on s1 and s2 let’s see what happen.
boom., It resolved. Notice the ip of dns server it’s 127.0.0.11 which local of container. And that dns server know about s1 and s2 because they are in same network. we can check traceroute as well to see where request is going.
Create second network
In our production environment we need more then one network because we use multiple service like nginx for web server, backend service, database service etc. It is possible to put all services in one network, but it can be risky from a security standpoint.
let’s create frontend network and put s2 server there.
docker network create frontend — subnet 10.0.1.0/24
docker network disconnect backend s2
docker network connect frontend s2
docker inspect s2
let’s bash into s1, and try to ping s2 this will not work in this case because s2 is in different subnet.
docker exec -it s1 bash # in host
How to solve this? using router, we need to create router and setup our own gateway,
docker run — name gw — network backend -d newhttpd # in host machine
docker network connect frontend gw # in host machine
docker exec -it gw bash # in host machine
ping s1 # in gw
ping s2 # in gw
we link s1 - gw - s2 or we can say gw <-> s1 and gw <-> s2, still s1 can not ping s2 and vice versa. but s1 can ping gw. for s1 <-> s2, we have to tell s1 that if try to access on subnet 10.0.1.0/24 then use gw gateway and and to s2 that if try to access on subnet 10.0.0.0/24 then use gw gateway. We have to set routes in s1 and s2 for this for that we can use,
ip route add <subnet> via <gatway ip>
we need admin prviledge for set route in container so stop and remove the container s1 and s2 and re run with — cap-add=NET_ADMIN option.
docker stop s1 s2 # in host machine
docker rm s1 s2 # in host machine
docker run --name s2 --network frontend --cap-add=NET_ADMIN -d newhttpd # in host machine
docker run --name s1 --network backend --cap-add=NET_ADMIN -d newhttpd # in host machine
check the gateway ip and set ip route in both containers,
docker exec -it s2 bash # in host machine
nslookup gw # in s2
ip route add 10.0.0.0/24 via 10.0.1.3 # in s2 and the ctrl + c
docker exec -it s1 bash # in host machine
nslookup gw # in s1
ip route add 10.0.1.0/24 via 10.0.0.2 # in s1
Now both container can talk with each other. still we can’t communicate with s1 and s2 but we can talk with ip address. So now we have two separate networks, and containers running on those networks can communicate with each other. Other then this network can not communicate or access this containers. ensuring network isolation and improving security.
We’re done for now. Happy learning …🙂