In this post, we feature a comprehensive article on Docker Link via Ambassador Container. I am going to demonstrate how the Docker Containers can be connected across Docker Hosts by using Ambassador Container or Pattern.
To understand about connecting Docker Containers across Docker Hosts by using Ambassador Pattern, we must first understand the concept of linking Docker Containers in a Single Host.
1. Linking Docker Containers in a single host
The following diagram shows that there are two docker containers (web application and Database) linked in a Single Docker Host.
Linking is a communication method between docker containers which allows them to securely transfer data from source to the recipient.
- Source and Recipient Containers
- Recipient Containers have access to data on Source containers
- Links are established based on Container names
We can link containers which will allow them to talk to each other without having to expose any Network Ports.
1.1 How to Create a Link between the Docker Containers?
- First, create the source container
- Create the recipient container and use the – – link option
Best Practice – Give your containers meaningful names
1.2 Docker Containers Link in a Single Docker Host Example
Let us create a container (a Redis server) and another container (a Redis client). The Redis client is used 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:
Note: $ designates your host machine prompt and # designates the container prompt.
You can check the effect of the linking alias in your redis_client:
Install ping: # apt-get update
# apt-get upgrade
# apt-get install iputils-ping
If you ping the Redis server, you should get a response back:
Let’s connect to the Redis server:
redis-cli -h redisDB
The new prompt redisDB:6379 means that you are connected to the Redis server. You can now enter information into the server.
Use of Linking:
- Containers can talk to each other without having to expose ports to the host
- Essential for micro service application architecture
1.3 Docker Containers Link in a Single Docker Host – Example
- Container with Tomcat running
- Container with MySQL running
- Application on Tomcat needs to connect to MySQL
You have a recipient container and the source container, You connect the recipient to the source and the recipient has access to the data on the source container. The links are established by using the container names.
The main use of Containing Linking is when you are building an application with a microservice architecture having many independent components running in their own container. These Components need to talk to each other. If you have a tomcat container with your webapp and on the backend is mysql container. webapp needs to connect to the database so you link those two containers together. mysql is the source container and tomcat is the recipient container.
2. Docker Link via ambassador container
One of the limitations of Docker is that they cannot link containers across docker hosts using the native link feature as we discussed above.
We can connect the Docker Containers over the network and across the different docker hosts using Ambassador Container.
In this Ambassador pattern, we can deploy an ambassador container in each host, and the ambassadors will link the containers together across the hosts.
Ambassadors are containers. They are used to help connect containers across multiple docker hosts.
How to connect Docker containers by using the ambassador pattern so that they can communicate over the network and across Docker hosts.?
The following diagram shows that there are two containers (web application and Database) are in different docker hosts, which are connected by using Ambassador Containers (Ambassador Pattern):
- The web application container uses normal Docker networking to connect to the ambassador.
- The database container also talks with an ambassador.
- For both containers, the ambassador is totally transparent.
- If the database container is moved (or a failover happens), its new location will be tracked by the ambassador containers, and the web application container will still be able to connect, without reconfiguration.
The following example shows how a Redis client container talk to the remote Redis server, just by linking to the local Redis ambassador:
In Docker Host 1: do the following:
$ docker run -d –name redis crosbymichael/redis – Start actual Redis server
In Docker Host 1: do the following
Add an ambassador linked to the Redis server, mapping a port to the outside world
$ docker run -d –link redis:redis –name redis_ambassador -p 6379:6379 svendowideit/ambassador
In Docker Host 2: do the following:
Set up another ambassador setting environment variables for each remote port we want to proxy to the Docker Host 1:
$ docker run -d –name redis_ambassador –expose 6379 -e REDIS_PORT_6379_TCP=tcp://192.168.1.52:6379 svendowideit/ambassador
In Docker Host 2: do the following:
Use a Redis client container to talk to the remote Redis server, just by linking to the local Redis ambassador:
client-server $ docker run -i -t –rm –link redis_ambassador:redis relateiq/redis-cli
redis 172.17.0.160:6379> ping
2.2 How does it work?
svendowideit/ambassador container automatically (with a tiny amount of
sed) does the following:
On the Docker host (192.168.1.52) that Redis will run on:
# Start actual redis server $ docker run -d --name redis crosbymichael/redis # Get a redis-cli image for connection testing $ docker pull relateiq/redis-cli # Test the redis server by talking to it directly $ docker run -t -i --rm --link redis:redis relateiq/redis-cli redis 172.17.0.136:6379> ping PONG ^D # Add redis ambassador $ docker run -t -i --link redis:redis --name redis_ambassador -p 6379:6379 alpine:3.2 sh
In the redis_ambassador container, you can see the linked Redis containers env:
\ # env REDIS_PORT=tcp://172.17.0.136:6379 REDIS_PORT_6379_TCP_ADDR=172.17.0.136 REDIS_NAME=/redis_ambassador/redis HOSTNAME=19d7adf4705e SHLVL=1 HOME=/root REDIS_PORT_6379_TCP_PORT=6379 REDIS_PORT_6379_TCP_PROTO=tcp REDIS_PORT_6379_TCP=tcp://172.17.0.136:6379 TERM=xterm PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin PWD=/ / # exit
This environment is used by the ambassador
socat script to expose Redis to the world (via the
-p 6379:6379 port mapping):
$ docker rm redis_ambassador $ CMD="apk update && apk add socat && sh" $ docker run -t -i --link redis:redis --name redis_ambassador -p 6379:6379 alpine:3.2 sh -c "$CMD" […] / # socat -t 100000000 TCP4-LISTEN:6379,fork,reuseaddr TCP4:172.17.0.136:6379
Now ping the Redis server via the ambassador:
Now go to a different server:
$ CMD="apk update && apk add socat && sh" $ docker run -t -i --expose 6379 --name redis_ambassador alpine:3.2 sh -c "$CMD" […] / # socat -t 100000000 TCP4-LISTEN:6379,fork,reuseaddr TCP4:192.168.1.52:6379
And get the
redis-cli image so we can talk over the ambassador bridge.
$ docker pull relateiq/redis-cli $ docker run -i -t --rm --link redis_ambassador:redis relateiq/redis-cli redis 172.17.0.160:6379> ping PONG
3. Docker Link via Ambassador Container – Summary
We have learned the following in this Docker Link via Ambassador Container Example:
- Linking Docker Containers in a Single Docker host using –link option
- Linking Docker Containers across Docker hosts using Ambassador Container Pattern