github.com/eikeon/docker@v1.5.0-rc4/docs/sources/articles/ambassador_pattern_linking.md (about) 1 page_title: Link via an Ambassador Container 2 page_description: Using the Ambassador pattern to abstract (network) services 3 page_keywords: Examples, Usage, links, docker, documentation, examples, names, name, container naming 4 5 # Link via an Ambassador Container 6 7 ## Introduction 8 9 Rather than hardcoding network links between a service consumer and 10 provider, Docker encourages service portability, for example instead of: 11 12 (consumer) --> (redis) 13 14 Requiring you to restart the `consumer` to attach it to a different 15 `redis` service, you can add ambassadors: 16 17 (consumer) --> (redis-ambassador) --> (redis) 18 19 Or 20 21 (consumer) --> (redis-ambassador) ---network---> (redis-ambassador) --> (redis) 22 23 When you need to rewire your consumer to talk to a different Redis 24 server, you can just restart the `redis-ambassador` container that the 25 consumer is connected to. 26 27 This pattern also allows you to transparently move the Redis server to a 28 different docker host from the consumer. 29 30 Using the `svendowideit/ambassador` container, the link wiring is 31 controlled entirely from the `docker run` parameters. 32 33 ## Two host Example 34 35 Start actual Redis server on one Docker host 36 37 big-server $ sudo docker run -d --name redis crosbymichael/redis 38 39 Then add an ambassador linked to the Redis server, mapping a port to the 40 outside world 41 42 big-server $ sudo docker run -d --link redis:redis --name redis_ambassador -p 6379:6379 svendowideit/ambassador 43 44 On the other host, you can set up another ambassador setting environment 45 variables for each remote port we want to proxy to the `big-server` 46 47 client-server $ sudo docker run -d --name redis_ambassador --expose 6379 -e REDIS_PORT_6379_TCP=tcp://192.168.1.52:6379 svendowideit/ambassador 48 49 Then on the `client-server` host, you can use a Redis client container 50 to talk to the remote Redis server, just by linking to the local Redis 51 ambassador. 52 53 client-server $ sudo docker run -i -t --rm --link redis_ambassador:redis relateiq/redis-cli 54 redis 172.17.0.160:6379> ping 55 PONG 56 57 ## How it works 58 59 The following example shows what the `svendowideit/ambassador` container 60 does automatically (with a tiny amount of `sed`) 61 62 On the Docker host (192.168.1.52) that Redis will run on: 63 64 # start actual redis server 65 $ sudo docker run -d --name redis crosbymichael/redis 66 67 # get a redis-cli container for connection testing 68 $ sudo docker pull relateiq/redis-cli 69 70 # test the redis server by talking to it directly 71 $ sudo docker run -t -i --rm --link redis:redis relateiq/redis-cli 72 redis 172.17.0.136:6379> ping 73 PONG 74 ^D 75 76 # add redis ambassador 77 $ sudo docker run -t -i --link redis:redis --name redis_ambassador -p 6379:6379 busybox sh 78 79 In the `redis_ambassador` container, you can see the linked Redis 80 containers `env`: 81 82 $ env 83 REDIS_PORT=tcp://172.17.0.136:6379 84 REDIS_PORT_6379_TCP_ADDR=172.17.0.136 85 REDIS_NAME=/redis_ambassador/redis 86 HOSTNAME=19d7adf4705e 87 REDIS_PORT_6379_TCP_PORT=6379 88 HOME=/ 89 REDIS_PORT_6379_TCP_PROTO=tcp 90 container=lxc 91 REDIS_PORT_6379_TCP=tcp://172.17.0.136:6379 92 TERM=xterm 93 PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin 94 PWD=/ 95 96 This environment is used by the ambassador `socat` script to expose Redis 97 to the world (via the `-p 6379:6379` port mapping): 98 99 $ sudo docker rm redis_ambassador 100 $ sudo ./contrib/mkimage-unittest.sh 101 $ sudo docker run -t -i --link redis:redis --name redis_ambassador -p 6379:6379 docker-ut sh 102 103 $ socat TCP4-LISTEN:6379,fork,reuseaddr TCP4:172.17.0.136:6379 104 105 Now ping the Redis server via the ambassador: 106 107 Now go to a different server: 108 109 $ sudo ./contrib/mkimage-unittest.sh 110 $ sudo docker run -t -i --expose 6379 --name redis_ambassador docker-ut sh 111 112 $ socat TCP4-LISTEN:6379,fork,reuseaddr TCP4:192.168.1.52:6379 113 114 And get the `redis-cli` image so we can talk over the ambassador bridge. 115 116 $ sudo docker pull relateiq/redis-cli 117 $ sudo docker run -i -t --rm --link redis_ambassador:redis relateiq/redis-cli 118 redis 172.17.0.160:6379> ping 119 PONG 120 121 ## The svendowideit/ambassador Dockerfile 122 123 The `svendowideit/ambassador` image is a small `busybox` image with 124 `socat` built in. When you start the container, it uses a small `sed` 125 script to parse out the (possibly multiple) link environment variables 126 to set up the port forwarding. On the remote host, you need to set the 127 variable using the `-e` command line option. 128 129 --expose 1234 -e REDIS_PORT_1234_TCP=tcp://192.168.1.52:6379 130 131 Will forward the local `1234` port to the remote IP and port, in this 132 case `192.168.1.52:6379`. 133 134 # 135 # 136 # first you need to build the docker-ut image 137 # using ./contrib/mkimage-unittest.sh 138 # then 139 # docker build -t SvenDowideit/ambassador . 140 # docker tag SvenDowideit/ambassador ambassador 141 # then to run it (on the host that has the real backend on it) 142 # docker run -t -i --link redis:redis --name redis_ambassador -p 6379:6379 ambassador 143 # on the remote host, you can set up another ambassador 144 # docker run -t -i --name redis_ambassador --expose 6379 sh 145 146 FROM docker-ut 147 MAINTAINER SvenDowideit@home.org.au 148 149 150 CMD env | grep _TCP= | sed 's/.*_PORT_\([0-9]*\)_TCP=tcp:\/\/\(.*\):\(.*\)/socat TCP4-LISTEN:\1,fork,reuseaddr TCP4:\2:\3 \&/' | sh && top