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 Container Links
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.
Docker Link Example
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:
- https://docs.docker.com/engine/userguide/networking/default_network/dockerlinks
- https://docs.docker.com/engine/userguide/networking
- https://docs.docker.com/engine/userguide/networking/work-with-networks
- https://stackoverflow.com/questions/41294305/docker-compose-difference-between-network-and-link
- https://stackoverflow.com/questions/39173670/are-docker-links-deprecated
- https://linuxconfig.org/basic-example-on-how-to-link-docker-containers
- Docker: Intro to Networking (Ep 5)[https://www.youtube.com/watch?v=C12Ba74i4YI]
- Docker Training 28/29: Linking Containers[https://www.youtube.com/watch?v=uSfW17zs35k]
- https://www.oreilly.com/learning/what-is-docker-networking
- http://www.dasblinkenlichten.com/docker-networking-101-user-defined-networks