5.7 Communicating Between Docker Containers

All containers are automatically added to the default bridge network and assigned IP addresses by the Docker Engine. This means that containers are effectively able to communicate directly using the bridge network. However there is no automatic service discovery on the default bridge network. If containers need to be able to resolve IP addresses by container name, you should use a user-defined network instead.

You can use the --link option with docker run to make network connection information about a server container available to a client container. For example to link a client container, client1, to a server container, httpd_server, you could run:

[root@host httpd]# docker run --rm -t -i --name client1 --link http-server:server \
  oraclelinux /bin/bash

The client container uses a private networking interface to access the exposed port in the server container. Docker sets environment variables about the server container in the client container that describe the interface and the ports that are available. The server container name and IP address are also set in /etc/hosts in the client container, to facilitate easy access.

The --link option is considered a legacy feature and may be deprecated in future releases. It is not recommended in most cases.

The preferred approach to setting up communications between containers is to create user-defined networks. These networks provide better isolation and can perform DNS resolution of container names to IP addresses. A variety of network drivers are available, but the most commonly used is the bridged network which behaves similarly to the default bridge network but which provides additional features.

The following example shows how to create a simple user-defined network bridge and how to connect containers to it, to allow them to communicate easily with each other.

  1. Create a network using the bridge driver.

    [root@host ~]# docker network create --driver bridge http_network
    4a03450bf054a6d4d4db52da36eab8d934d35bf961b3b3adb4fe20be54c0fdac

    In the example, the network is named http_network.

    You can check that the network has been created and which driver it is using:

    [root@host ~]# docker network ls
    NETWORK ID          NAME                DRIVER              SCOPE
    094c50739e14        bridge              bridge              local
    7eff8115af9a        host                host                local
    4a03450bf054        http_network        bridge              local
    457c4070f5a2        none                null                local

    You can also inspect the network object to discover more information:

    [root@host ~]# docker network inspect http_network
    [
        {
            "Name": "http_network",
            "Id": "4a03450bf054a6d4d4db52da36eab8d934d35bf961b3b3adb4fe20be54c0fdac",
            "Created": "2019-02-06T04:40:47.177691733-08:00",
            "Scope": "local",
            "Driver": "bridge",
            "EnableIPv6": false,
            "IPAM": {
                "Driver": "default",
                "Options": {},
                "Config": [
                    {
                        "Subnet": "172.18.0.0/16",
                        "Gateway": "172.18.0.1"
                    }
                ]
            },
            "Internal": false,
            "Attachable": false,
            "Ingress": false,
            "ConfigFrom": {
                "Network": ""
            },
            "ConfigOnly": false,
            "Containers": {},
            "Options": {},
            "Labels": {}
        }
    ]
  2. Connect existing containers to the user-defined network.

    [root@host ~]# docker network connect http_network http-server
    [root@host ~]# docker network connect http_network client1

    In this example, http-server and client1 are existing containers that are connected to the newly created http_network bridge network.

  3. Connect a new container to the user-defined network, using the --network option.

    [root@host ~]# docker run --rm -t -i --name client2 --network http_network oraclelinux:7 /bin/bash

    You can check that domain name resolution is working from within the container by pinging any other container on the network by its container name:

    [root@client1 ~]# ping -c 1 http-server
    PING http-server (172.18.0.2) 56(84) bytes of data.
    64 bytes from http-server.http_network (172.18.0.2): icmp_seq=1 ttl=64 time=0.162 ms
    
    --- http-server ping statistics ---
    1 packets transmitted, 1 received, 0% packet loss, time 0ms
    rtt min/avg/max/mdev = 0.162/0.162/0.162/0.000 ms

    You can access services on containers within the network using their container names. For example:

    [root@client1 ~]# curl http://http-server
    HTTP server running on guest

For more information, see https://docs.docker.com/engine/userguide/networking/.