Docker Container Links

Docker is an easy-to-use container technology for single applications. Regardless of expertise level, users can easily set up docker and start using it for useful experimentation. However, as users try to work with more complex setups that require services to talk to each other, it’s necessary to learn about docker networking techniques. Let’s discuss docker linking and docker networking features.

Docker link is a deprecated legacy feature. It was the main way of connecting containers before the introduction of Docker networking feature in version 1.9.  Docker links may be removed in the future. So it is recommended that new designs avoid using this method. However, users should have an idea about how linking works in case they run into legacy code.

Let’s create a container to work as a Redis server and another container to work as a Redis client. Redis is an in-memory database. We will use the Redis client to enter information into the Redis server.  The following command will start a Redis server called redis_server:

$ docker run -d --name redis_server redis

Let’s start the interactive Redis client called redis_client with the following command:

$ docker run -it --name redis_client --link redis_server:redisDB redis bash

The “link” option is linking to the redis_server while giving it the alias redisDB. After executing the command, you should see a command prompt like this:

root@e2364251d31d:/data# 

(Note: $ designates your host machine prompt and # designates the container prompt).

You can check the effect of the linking alias in your redis_client:

# cat /etc/hosts
127.0.0.1    localhost
::1    localhost ip6-localhost ip6-loopback
fe00::0    ip6-localnet
ff00::0    ip6-mcastprefix
ff02::1    ip6-allnodes
ff02::2    ip6-allrouters
172.17.0.2    redisDB 30013915ec69 redis_server
172.17.0.3    e2364251d31d

Let’s install ping:

# apt-get update
# apt-get upgrade
# apt-get install iputils-ping

If you ping the Redis server, you should get a reply back:

# ping redisDB

PING redisDB (172.17.0.2) 56(84) bytes of data.
64 bytes from redisDB (172.17.0.2): icmp_seq=1 ttl=64 time=0.308 ms
64 bytes from redisDB (172.17.0.2): icmp_seq=2 ttl=64 time=0.095 ms
^C
--- redisDB ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1004ms
rtt min/avg/max/mdev = 0.095/0.201/0.308/0.107 ms

Let’s connect to the Redis server:

# redis-cli -h redisDB

redisDB:6379>  

The new prompt redisDB:6379 means that you are connected to the Redis server. You can play around and enter information into the server.

redisDB:6379> ping
PONG
redisDB:6379> set book "Great Expectations"
OK
redisDB:6379> set author "Charles Dickens"
OK
redisDB:6379> get book
"Great Expectations"
redisDB:6379> get author
"Charles Dickens"

If you look at the processes running on your host machine, you should see both containers:

$ docker ps
CONTAINER ID	IMAGE	COMMAND			CREATED		STATUS		PORTS	NAMES
e2364251d31d	redis	"docker-entrypoint..."	21 minutes ago	Up 21 minutes	6379/tcp	redis_client
30013915ec69	redis	"docker-entrypoint..."	29 minutes ago	Up 29 minutes	6379/tcp	redis_server

In the above example, you created redis_server and then linked redis_client to it. But as you can see from this simple example, the process will grow unmanageable with multiple containers talking to each other. You have to remember to link all the containers. Docker networking feature was created to simplify the process.

Docker Networking

With the introduction of the Docker networking feature in version 1.9, Docker creates three networks automatically. The following command on the host machine should show the networks:

$ docker network ls

NETWORK ID		NAME		DRIVER	SCOPE
c717bef82db7	bridge 	bridge	local
f94edefb6b2d	host		host		local
83d38b096d00	none		null		local

The three automatically created networks are bridge, host and none. Let’s have a look at each:

  • bridge: The bridge network represents docker0, a virtual Ethernet bridge that forwards packets to other network interfaces attached to it. By default, all new containers are added to this bridge if no other option is specified. Users can also create their own custom bridges.
  • host: The host network adds containers to the host’s network stack. If you define a container on the host network, then the separation between host and container is gone, eg. an open port 80 in the container means an open port 80 on the host.
  • none: The none network is to turn off networking. It can be useful for applications that don’t need a network for testing or some other purpose.

Docker Networking Example Using User-Defined Bridge Network

Let’s try out the Redis server example using a Docker user-defined bridge network.  First, you can create a network called “internal_network” with the following command:

$ docker network create --driver bridge internal_network

If you inspect the network, you will find that it has created a subnet and a gateway:

$ docker network inspect internal_network
[
    {
        "Name": "internal_network",
        "Id": "9bc2213d3a39d46765fe50ef8e9b7819df8e7124b0a46552447cbda84e31b049",
        "Created": "2017-11-02T08:01:05.119528611Z",
        "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": {}
    }
]

Listing all the networks should show the newly created bridge network:

$ docker network ls

NETWORK ID          NAME                DRIVER              SCOPE
c717bef82db7        bridge              bridge              local
f94edefb6b2d        host                host                local
9bc2213d3a39        internal_network    bridge              local
83d38b096d00        none                null                local

You can create the Redis server called redis_server attached to the internal_network bridge:

$ docker run -d --network=internal_network --name=redis_server redis

Now, let’s create the redis_client attached to the network bridge:

$ docker run -it --network=internal_network --name=redis_client redis bash

root@e8f6d515cb5e:/data# 

(Note: $ designates your host machine prompt and # designates the container prompt).

If you inspect the internal_network again, you should see that the two containers have been added to the bridge network:


$ docker network inspect internal_network

From your redis_client, you should be able to ping redis_server and connect to it.

# ping redis_server

PING redis_server (172.18.0.2) 56(84) bytes of data.
64 bytes from redis_server.internal_network (172.18.0.2): icmp_seq=1 ttl=64 time=0.169 ms
64 bytes from redis_server.internal_network (172.18.0.2): icmp_seq=2 ttl=64 time=0.188 ms
64 bytes from redis_server.internal_network (172.18.0.2): icmp_seq=3 ttl=64 time=0.151 ms
^C
--- redis_server ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2064ms
rtt min/avg/max/mdev = 0.151/0.169/0.188/0.018 ms


# redis-cli -h redis_server

redis_server:6379> PING
PONG
redis_server:6379> set book "Tale of Two Cities"
OK
redis_server:6379> set author "Charles Dickens"
OK
redis_server:6379> get book
"Tale of Two Cities"
redis_server:6379> get author
"Charles Dickens"
redis_server:6379> 

Notice that you don’t have to actively link the containers. You created a network internal_network and put all your containers inside it. It makes the setup much simpler when you are dealing with multiple containers.

The internal_network is not accessible from outside. But you can open up ports using the publish or expose port on the docker run command.

Further Study:

 The above examples only dealt with single host situations. For multi-host situations, you will need to look into Docker Compose and Docker Swarm. Also, you can find more information about Docker networking from the following documentation:

References:

How to Install and Use Docker on Ubuntu

Total
0
Shares
Leave a Reply

Your email address will not be published. Required fields are marked *

Previous Post

JNI Tutorial

Next Post

Java8 vs Java9

Related Posts