Series on Docker in Practice & Production - Network in Docker

Series on Docker in Practice & Production - Network in Docker

Daily short news for you
  • Now everything is so modern that people can come up with anything. ferretdb.com is an open-source project that transforms the PostgreSQL database into... MongoDB. That's right, you heard it correctly. If you still want to use Postgres but prefer the Mongo query syntax, then ferretdb is for you.

    Oh, besides PostgreSQL, it can also connect to SQLite. Awesome!!! 🙏

    » Read more
  • Dedicating this to those of you using Cursor. PatrickJS/awesome-cursorrules gathers some .cursorrules files to optimize prompts for Cursor. Imagine these files as the System Prompt for Cursor, controlling it according to your wishes in each project.

    The usage is really simple, just copy the appropriate .cursorrules file and place it in the root folder of the project 🥳

    » Read more
  • Gemini 2.5 has just been released, everyone. This is the most advanced model from Google to date, with top-notch reasoning and coding capabilities - as they introduce it.

    Everyone, take a look at the benchmark table; the metrics are all superior to the other competitors. We don't know the price yet, but you can try it for free in Google AI Studio. I guess we’ll wait for it to be integrated into Cursor to see how its coding abilities measure up 😁

    » 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

The secret stack of Blog

As a developer, are you curious about the technology secrets or the technical debts of this blog? All secrets will be revealed in the article below. What are you waiting for, click now!

As a developer, are you curious about the technology secrets or the technical debts of this blog? All secrets will be revealed in the article below. What are you waiting for, click 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...