Series on Docker in Practice & Production - Network in Docker

Series on Docker in Practice & Production - Network in Docker

Daily short news for you
  • Manus has officially opened its doors to all users. For those who don't know, this is a reporting tool (making waves) similar to OpenAI's Deep Research. Each day, you get 300 free Credits for research. Each research session consumes Credits depending on the complexity of the request. Oh, and they seem to have a program giving away free Credits. I personally saw 2000 when I logged in.

    I tried it out and compared it with the same command I used before on Deep Research, and the content was completely different. Manus reports more like writing essays compared to OpenAI, which uses bullet points and tables.

    Oh, after signing up, you have to enter your phone number for verification; if there's an error, just wait until the next day and try again.

    » Read more
  • I just found a quite interesting website talking about the memorable milestones in the history of the global Internet: Internet Artifacts

    Just from 1977 - when the Internet was still in the lab - look how much the Internet has developed now 🫣

    » Read more
  • Just thinking that a server "hiding" behind Cloudflare is safe, but that’s not necessarily true; nothing is absolutely safe in this Internet world. I invite you to read the article CloudFlair: Bypassing Cloudflare using Internet-wide scan data to see how the author discovered the IP address of the server that used Cloudflare.

    It's quite impressive, really; no matter what, there will always be those who strive for security and, conversely, those who specialize in exploiting vulnerabilities and... blogging 🤓

    » Read more

Problem

One of the reasons that Docker has become powerful is its networking system, which allows containers to easily connect with each other, regardless of whether they are running in a Docker environment or on different Docker platforms like Linux, Windows, or MacOS. To understand this in more detail, let's dive into the topic of networking in Docker.

Network drivers

Docker provides several network drivers for different use cases:

  • Bridge: This is the default driver when creating a network if you don't specify a driver. It allows containers to communicate with each other if they are part of the same network.
  • Host: This driver allows containers to directly use the host's network. In other words, containers using this driver won't use Docker's network, but the host's network instead.
  • Overlay: This driver connects multiple Docker hosts together through Docker Swarm, allowing containers within those hosts to communicate with each other.
  • None: As the name suggests, this driver isolates your containers from the internet.

In addition, there are also macvlan and third-party plugins, but we won't cover them in this article. If you're interested, you can explore them on the Docker website.

Creating a network

Docker provides commands to easily create a network.

$ docker network create -d bridge estacks-network --attachable

Here, I have created a network called "estacks-network" with the bridge driver. The -d flag allows me to specify the driver Docker supports, and --attachable allows containers to manually connect to the network using commands.

To create a new container and specify its connection to the network:

$ docker run --network estacks-network --name nginx -d nginx

To connect an existing container to the network:

$ docker network connect estacks-network mysql

Here, "mysql" is the name of the container.

There are many more commands that I cannot list here, but you can refer to the Docker network documentation for more details and usage.

Using drivers in different scenarios

One thing is certain: for containers to communicate with each other, they must be part of the same network. "Communication" here refers to their ability to exchange data. Therefore, if you encounter connectivity issues while deploying your application, you should check if there are any network problems.

There are several ways to deploy containers and enable them to communicate with each other. Here are a few approaches that I often use:

Deploying independent containers

For example, if you simply want to run a MySQL container as a database for your development environment, you can use the docker run command:

$ docker run --name mysql -d mysql

When no network is specified, the container will default to the bridge network, and it will be assigned a fixed IP address within that network. Any container running in the bridge network will be able to call each other using their IP addresses:

$ docker inspect mysql
{
  ...  
  "NetworkSettings": {
    ...  
    "Networks": {
      "bridge": {
        "IPAMConfig": null,  
        "Links": null,  
        "Aliases": null,  
        "NetworkID": "22a978aa722c09d9636cfcc4e6dedb4c788cf839421201a00a004596e812f0e1",  
        "EndpointID": "a72743fdd788e759ed3358d3dd043122be08d5f5dcc8cd20144e55d7161f433c",  
        "Gateway": "172.17.0.1",  
        "IPAddress": "172.17.0.3",  
        "IPPrefixLen": 16,  
        "IPv6Gateway": "",  
        "GlobalIPv6Address": "",  
        "GlobalIPv6PrefixLen": 0,  
        "MacAddress": "02:42:ac:11:00:03",  
        "DriverOpts": null
      }
    }
  }
}

Tip: Use the docker inspect command to view detailed information about a container.

As you can see from the above example, the MySQL container has an IP address of 172.17.0.3. Now, let's say I want to create another container, nginx, also using the bridge network. I will access that container and try to ping the address 172.17.0.3 to see if it receives any response:

$ docker run -d --name nginx nginx
$ docker exec -it nginx bash
root@02d4d43a19fd:/# ping 172.17.0.3
PING 172.17.0.3 (172.17.0.3) 56(84) bytes of data.  
64 bytes from 172.17.0.3: icmp_seq=1 ttl=64 time=0.045 ms
64 bytes from 172.17.0.3: icmp_seq=2 ttl=64 time=0.038 ms
64 bytes from 172.17.0.3: icmp_seq=3 ttl=64 time=0.035 ms
64 bytes from 172.17.0.3: icmp_seq=4 ttl=64 time=0.035 ms
^C
--- 172.17.0.3 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 115ms
rtt min/avg/max/mdev = 0.035/0.038/0.045/0.006 ms

As you can see, because they are both part of the bridge network, they can communicate with each other if the IP address is known.

However, these containers can only call each other if they are part of the same network. If I try to ping MySQL from the terminal, I won't receive any response. Why? Because my terminal is not connected to Docker's bridge network. To achieve that, Docker provides a mechanism that you might already know, which is to expose the port of the MySQL container externally. In simple terms, that means mapping the port of MySQL to a different port on the host, so we can connect to the container through that port.

$ docker run -d --name mysql2 -p 3306:3307 mysql
$ telnet localhost 3307

The -p 3306:3307 flag denotes exposing the port 3306 of the container to port 3307 of the host. Port 3307 will be the port to communicate with MySQL inside the container. Now, I can use the MySQL server through localhost:3307.

What if I want containers to use the Docker host's network?

Instead of using the -p flag to expose individual ports in Docker, I can run containers on the host. When a container is specified to run on the host, it won't be bound by Docker's network anymore. For example:

$ docker run --network host --name mysql -d mysql

In the terminal, I try to telnet to port 3306:

$ telnet localhost 3306
Trying ::1...  
Connected to localhost.  
Escape character is '^]'.  

Docker for Windows or MacOS actually runs inside a Linux virtual machine, so when using the host option, Docker uses the network of that virtual machine. Therefore, if you are using Windows and want to telnet to the MySQL container while using "localhost," it won't work:

$ telnet localhost 3306
Trying ::1...  
telnet: connect to address ::1: Connection refused

Instead of using "localhost," you can try using the IP address of the running Docker virtual machine.

What about containers in Docker Compose?

I have written an article about Docker Compose for orchestrating multiple services.

In the docker-compose.yml file, you'll notice that each service needs to be part of the networks section. This networks section is not limited, and you can connect services to each other as you wish, as long as they are part of the same network. The networks declared in the docker-compose.yml will exist within that stack. In other words, when you start the compose, the network will be created, and when you shut down the compose, the network will be destroyed. You can also create a network first and join the services to that network.

$ docker network create my-network -d bridge --attachable

The -d bridge flag specifies creating a network with the bridge driver, and --attachable allows containers to join manually. Refer to the docker create command documentation for more details.

In the docker-compose.yml:

version: "3.9"
services:  
  mysql:  
    ...  
    networks:  
      - my-network
    ...  
  ...  

networks:  
  my-network:  
    external: true

Lastly, what's different about overlay?

When Docker is deployed in swarm mode, each node may have different IP addresses. To simplify communication between containers on different nodes, Docker provides the overlay driver.

In simple terms, if containers on different nodes are part of the same overlay network, they can communicate with each other.

If you're not familiar with Docker swarm, don't worry—I have planned the next article in this series to cover that topic.

Summary

Networking in Docker makes it easy for containers to communicate with each other because containers are independent entities. Docker also provides various network drivers to cater to different usage needs, such as bridge, host, overlay, and more. One crucial principle to remember in deployment and troubleshooting is that containers need to be part of the same network to communicate with each other.

Premium
Hello

Me & the desire to "play with words"

Have you tried writing? And then failed or not satisfied? At 2coffee.dev we have had a hard time with writing. Don't be discouraged, because now we have a way to help you. Click to become a member now!

Have you tried writing? And then failed or not satisfied? At 2coffee.dev we have had a hard time with writing. Don't be discouraged, because now we have a way to help you. Click to become a member now!

View all

Subscribe to receive new article notifications

or
* The summary newsletter is sent every 1-2 weeks, cancel anytime.

Comments (0)

Leave a comment...