A few days ago, in order to solve the daily local daily work and development test between the contradiction, using Docker in Windows system built based on Linux test environment: with the help of Docker, coding in Win10, a key in Linux test. This article mainly introduces how to build an environment basically consistent with the production environment through Docker locally and run and test our code with one click. Docker officially suggests that only one service should be run in each container [1], but our project may be composed of multiple services, which may require the support of mysql, Redis and other middleware. Therefore, we usually divide different services of a project into different containers. Although this approach has the advantages of low coupling and high isolation, it also increases the complexity of communication between services.

Communication modes between Docker containers can be divided into volume shared communication and network communication according to media. According to the range of communication can also be divided into: with the host communication and cross-host communication. This paper mainly discusses the network communication between containers.

1. Docker’s network driving model

Docker network driver model classification:

  • Bridge: the default network driver model in Docker. If this type is not specified when starting the container, it defaults to this driver type.
  • Host: Break the network isolation between the Docker container and the host, and directly use the network environment of the host. This model is only applicable to Docker17.6 and later versions;
  • Overlay: Can connect multiple Docker daemons or enable communication between cluster services; Communication between Docker containers applicable to different hosts;
  • Macvlan: It can assign MAC addresses to docker containers to make them run like real physical machines.
  • None: indicates that the network driver is disabled and you need to manually customize the network driver configuration.
  • Plugins: Use third-party network driver plugins;

The above are several network driving models supported by Docker, all of which have unique characteristics and application scope. In order to understand the network operation principle of Docker in more detail, several more important network models are selected for study.

2. bridge

2.1 Default bridge for Docker

The diagram of bridge driver mode in Docker is shown in the figure above, where the blue module represents the network card on the host. When Docker starts, a virtual bridge docker0 will be automatically created on the host. When Docker container is created using the default network mode, a pair of Veth pair interfaces will be automatically created. One end is connected to the Docker container (eth0 in the container shown in the figure). One end is connected to the virtual bridge Docker0 (see VeTH). This Veth pair is a virtual network device that is primarily used for network communication in different namespaces (meaning network isolation) and always exists in pairs. Here it can be imagined as a pair of virtual network cards connected by virtual network lines, one end is connected to the Docker container, one end is connected to the virtual bridge Docker0.

In this way, different Docker containers can communicate with each other through IP addresses, and can also access eth0 on the host network through virtual Bridges (add iptables rules to change the access from docker containers to the target address through address camouflage to the host’s access to the target address).

If you want external network to access docker container, you need to add parameter ‘-p [host port]:[container port]’ when Docker container is started for port mapping. The principle is also to forward data accessing [host port] to [container port] of Docker container by modifying iptables rules. However, this method also has the disadvantage of occupying the limited port resources of the host.

You can run the docker network ls command on the host to view the networks in the Docker:

docker network ls
#Output result:
NETWORK ID          NAME                DRIVER              SCOPE
e79b7548b225        bridge              bridge              local
666d5f1f459d        host                host                local
d0d785cf4794        none                null                local
Copy the code

Then run the docker network inspect bridge command to view the detailed configuration of the bridge network:

docker network inspect bridge
#Output result:[ { "Name": "bridge", "Id": "e79b7548b225c3c80d0f70d0de0b5911ed70a7f39ac20f75a8ae71c5cef05b3a", "Created": "2019-05-17t13:01:27.658164z ", "Scope": "local", "Driver": "bridge", # bridge Driver mode: false, "IPAM": {"Driver": "default", "Options": null, "Config": [{"Subnet": "172.17.0.0/16", # Subnet, docker container IP address "Gateway": The network configuration of the two Docker Containers (one mysql container, one Web service container) is "172.17.0.1". {# mysql container "d6f33e9bbd60e10d02dd2eebea424a7fc129d9646c96742ec3fe467833017679" : {" Name ":" mysqld5.7 ", "EndpointID" : "32e900f33367e3570c416c43a5618bd7a742cf94f36799e92895951ed1784736", "MacAddress": "02:42:ac:11:00:02", "IPv4Address": "172.17.0.2/16", # IPv6Address": ""}, # based on the tornado Web service container" dd292d535d16bbfe5382e29486756f4dddfea8e9b10af769db61618d739c5c4e ": {" Name" : "test_demo", "EndpointID": "eaf8e294f7b54aa50c6e6b30ac91f63b1a0ccbc5b56d6fbdcfeacd0471b15eb3", "MacAddress": "02:42: ac: 11:00:03", "IPv4Address" : "172.17.0.3/16", # container IP "IPv6Address" : ""}}," Options ": { "com.docker.network.bridge.default_bridge": "true", "com.docker.network.bridge.enable_icc": "true", "com.docker.network.bridge.enable_ip_masquerade": "true", "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0", "com.docker.net work. Bridge. The name" : "docker0", "com.docker.net work. Driver. Mtu" : "1500"}, "Labels" : {}}]Copy the code

As can be seen from the above configuration information, the gateway IP address of the Docker bridge is “172.17.0.1”, also known as Docker0, and the docker subnet is “172.17.0.0/16”. Docker will assign IP addresses to containers in “172.17.0.0/16”. For example, the IP address of the mysql container is 172.17.0.2/16 and the IP address of the test_demo container is 172.17.0.3/16. Because different containers are connected to the virtual bridge docker0 through veth pair, containers can communicate with each other through IP, but cannot communicate with each other through container name:

#Accessing mysqLD5.7 from test_demo container (via IP)Ping 172.17.0.2-3 c#Output result:PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data. 64 bytes from 172.17.0.2: Icmp_seq =1 TTL =64 time=0.147 ms 64 bytes from 172.17.0.2: ICmp_seq =2 TTL =64 time=0.185 ms 64 bytes from 172.17.0.2: Icmp_seq =3 TTL =64 time= 0.139ms -- 172.17.0.2 ping statistics -- 3 packets transmitted, 3 received, 0% packet loss Time 2057ms RTT min/avg/ Max /mdev = 0.147/0.180/0.209/0.027ms

#Accessing mysqLD5.7 from test_demo (by container name)Ping mysqld5.7#Output result:Ping: mysqld5.7: Name or service not knownCopy the code

Therefore, containers on the default bridge can only be connected by IP and cannot be resolved by DNS for names or aliases. So if we deploy a Web service in Container1, if we deploy mysql in Container2, the Web service in Container1 is going to have to connect to Container2’s mysql, which is IP only, However, Docker cannot guarantee that the IP address of the container will remain unchanged after the container is restarted. Therefore, a better way is to connect the container through alias, add a DNS server in the network, and match the container name with THE IP address, eliminating the process of manually changing the IP address of the connection to mysql in the Web service.

In order to interconnect different containers by container name or alias, Docker provides the following:

  1. –link parameter is added when docker container is started, but it has been abandoned at present. The main reason for abandonment is that the –link option needs to be created on both connected containers. When the number of interconnected containers is large, the operation complexity will increase significantly.

  2. After starting the docker container, enter the container and modify the /etc/host configuration file. The disadvantage is that manual configuration is complicated.

  3. User-defined bridge network bridge is the main method to solve this kind of problem at present.

2.2 User-defined Bridge

The main advantages of a user-defined bridge over the default bridge are:

  • User-defined Bridges can provide better performance in containerized applicationsThe isolation effectAnd betterinteroperability: This paragraph may seem contradictory, but it isBetter isolationIt’s for the outside network, andBetter interoperabilityIt means the samebridgeBetween different containers under. For example, container1 and Container2 deploy the Web service and mysql service respectively. Container1 only exposes the Web service to the external network80Port. Container2 only needs to connect to Container1 and does not need to be exposed, effectively protecting the security of the back-end container and improving the isolation effect of the container. Both are user-definedbridgeAll ports between container1 and Container2 are automatically exposed, facilitating barrier-free communication between container1 and container2 without accidental access.
  • User-defined Bridges provide automatic DNS resolution between containers: This is the focus of this article. Unlike the default bridge, which can only be connected by IP, user-defined Bridges automatically provide DNS resolution between containers. Containers can communicate by container names or aliases.
2.2.1 How to Use a User-defined Bridge
  1. Create a user-defined bridge:

    Docker network create my-net # create a network named "my-net"Copy the code
  2. Add the Web service container and mysql service container to “my-net” and observe the changes:

    Docker network connect my-net mysqld5.7 # Add mysql services to the My-Net networkCopy the code
    #View the network configuration for My-Net
    docker network inspect my-net
    #Output (omitted) :[ { "Name": "my-net", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Config": [ { "Subnet": "172.18.0.0/16", # my - net subnet "Gateway" : "172.18.0.1" # my - net Gateway}}], "Containers" : {" d6f33e9bbd60e10d02dd2eebea424a7fc129d9646c96742ec3fe467833017679 ": {" Name" : "mysqld5.7", "EndpointID" : "7d0e8d70bb523cceb4d2d8d4e3f8231fc68332c70f7f9b4e5d4abccce2b31a65", "MacAddress": "02:42:ac:12:00:03", "IPv4Address": "172.18.0.3/16", # IPv6Address": "" }, "dd292d535d16bbfe5382e29486756f4dddfea8e9b10af769db61618d739c5c4e": { "Name": "test_demo", "EndpointID": "f7802f1af81e258f77e227609dfdcdf66c49f19776381eb8b0dca6d9e794ccad", "MacAddress": "02:42:ac:12:00:02", "IPv4Address": "172.18.0.2/16", # IP address of Web service container, different from previous "IPv6Address": ""}},}]Copy the code

    As shown above, the subnet of the user-defined network my-net is “172.18.0.0/16”, so the IP addresses of the two Docker containers in the My-Net network are: “172.18.0.3/16” and “172.18.0.2/16”, and “172.17.0.2/16” before, “172.17.0.3/16”.

  3. Connect by container name or alias: Enter Web server container1 connect to Container2:

    Ping mysqld5.7-3 c#Output result:PING mysqld5.7 (172.18.0.3) 56(84) bytes of data.64 bytes from mysqld5.7.my-net (172.18.0.3): Icmp_seq =1 TTL =64 time=0.066 ms 64 bytes from mysqld5.7.my-net (172.18.0.3): Icmp_seq =2 TTL =64 time=0.145 ms 64 bytes from mysqld5.7.my-net (172.18.0.3): Icmp_seq =3 TTL =64 time= 0.75ms -- mysqld5.7 ping statistics -- 3 packets transmitted, 3 received, 0% packet loss, Time 2048ms RTT min/avg/ Max /mdev = 0.066/0.118/0.145/0.036msCopy the code

    As shown above, we can already connect to the mysql server with the container name “mysqLD5.7”.

  4. Disconnect from the network: Since our container is still connected to the default BridgeDocker0 and we no longer need it, we should disconnect the container from docker0 by doing the following:

    #Disconnect the container from docker0Docker network disconnect Bridge test_demo Docker network disconnect Bridge mysqLD5.7Copy the code

3. overlay

Key words: cross-host communication, cluster

To be continued.


  1. Run multiple services in a container. Docs.docker.com/config/cont… ↩ ︎