github.com/feiyang21687/docker@v1.5.0/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