Series on Docker in Practice & Production - Network in Docker

Series on Docker in Practice & Production - Network in Docker

Daily short news for you
  • Privacy Guides is a non-profit project aimed at providing users with insights into privacy rights, while also recommending best practices or tools to help reclaim privacy in the world of the Internet.

    There are many great articles here, and I will take the example of three concepts that are often confused or misrepresented: Privacy, Security, and Anonymity. While many people who oppose privacy argue that a person does not need privacy if they have 'nothing to hide.' 'This is a dangerous misconception, as it creates the impression that those who demand privacy must be deviant, criminal, or wrongdoers.' - Why Privacy Matters.

    » Read more
  • There is a wonderful place to learn, or if you're stuck in the thought that there's nothing left to learn, then the comments over at Hacker News are just for you.

    Y Combinator - the company behind Hacker News focuses on venture capital investments for startups in Silicon Valley, so it’s no surprise that there are many brilliant minds commenting here. But their casual discussions provide us with keywords that can open up many new insights.

    Don't believe it? Just scroll a bit, click on a post that matches your interests, check out the comments, and don’t forget to grab a cup of coffee next to you ☕️

    » Read more
  • Just got played by my buddy Turso. The server suddenly crashed, and checking the logs revealed a lot of errors:

    Operation was blocked LibsqlError: PROXY_ERROR: error executing a request on the primary

    Suspicious, I went to the Turso admin panel and saw the statistics showing that I had executed over 500 million write commands!? At that moment, I was like, "What the heck? Am I being DDoSed? But there's no way I could have written 500 million."

    Turso offers users free monthly limits of 1 billion read requests and 25 million write requests, yet I had written over 500 million. Does that seem unreasonable to everyone? 😆. But the server was down, and should I really spend money to get it back online? Roughly calculating, 500M would cost about $500.

    After that, I went to the Discord channel seeking help, and very quickly someone came in to assist me, and just a few minutes later they informed me that the error was on their side and had restored the service for me. Truly, in the midst of misfortune, there’s good fortune; what I love most about this service is the quick support like this 🙏

    » 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...