github.com/slene/docker@v1.8.0-rc1/docs/articles/ambassador_pattern_linking.md (about)

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