ambassador_pattern_linking.rst 5.4 KB

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