start-two-nodes-in-docker.sh 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. #!/usr/bin/env bash
  2. set -euo pipefail
  3. ## EMQX can only start with longname (https://erlang.org/doc/reference_manual/distributed.html)
  4. ## The host name part of EMQX's node name has to be static, this means we should either
  5. ## pre-assign static IP for containers, or ensure containers can communiate with each other by name
  6. ## this is why a docker network is created, and the containers's names have a dot.
  7. # ensure dir
  8. cd -P -- "$(dirname -- "$0")/../../"
  9. IMAGE1="${1}"
  10. IMAGE2="${2:-${IMAGE1}}"
  11. NET='emqx.io'
  12. NODE1="node1.$NET"
  13. NODE2="node2.$NET"
  14. COOKIE='this-is-a-secret'
  15. ## clean up
  16. docker rm -f haproxy >/dev/null 2>&1 || true
  17. docker rm -f "$NODE1" >/dev/null 2>&1 || true
  18. docker rm -f "$NODE2" >/dev/null 2>&1 || true
  19. docker network rm "$NET" >/dev/null 2>&1 || true
  20. docker network create "$NET"
  21. docker run -d -t --restart=always --name "$NODE1" \
  22. --net "$NET" \
  23. -e EMQX_LOG__CONSOLE_HANDLER__LEVEL=debug \
  24. -e EMQX_NODE_NAME="emqx@$NODE1" \
  25. -e EMQX_NODE_COOKIE="$COOKIE" \
  26. -e EMQX_CLUSTER__PROTO_DIST='inet_tls' \
  27. -e EMQX_listeners__ssl__default__enable=false \
  28. -e EMQX_listeners__wss__default__enable=false \
  29. -e EMQX_listeners__tcp__default__proxy_protocol=true \
  30. -e EMQX_listeners__ws__default__proxy_protocol=true \
  31. "$IMAGE1"
  32. docker run -d -t --restart=always --name "$NODE2" \
  33. --net "$NET" \
  34. -e EMQX_LOG__CONSOLE_HANDLER__LEVEL=debug \
  35. -e EMQX_NODE_NAME="emqx@$NODE2" \
  36. -e EMQX_NODE_COOKIE="$COOKIE" \
  37. -e EMQX_CLUSTER__PROTO_DIST='inet_tls' \
  38. -e EMQX_listeners__ssl__default__enable=false \
  39. -e EMQX_listeners__wss__default__enable=false \
  40. -e EMQX_listeners__tcp__default__proxy_protocol=true \
  41. -e EMQX_listeners__ws__default__proxy_protocol=true \
  42. "$IMAGE2"
  43. mkdir -p tmp
  44. cat <<EOF > tmp/haproxy.cfg
  45. ##----------------------------------------------------------------
  46. ## global 2021/04/05
  47. ##----------------------------------------------------------------
  48. global
  49. log stdout format raw daemon debug
  50. # Replace 1024000 with deployment connections
  51. maxconn 1000
  52. nbproc 1
  53. nbthread 2
  54. cpu-map auto:1/1-2 0-1
  55. tune.ssl.default-dh-param 2048
  56. ssl-default-bind-ciphers ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:DES-CBC3-SHA:HIGH:SEED:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!RSAPSK:!aDH:!aECDH:!EDH-DSS-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA:!SRP
  57. # Enable the HAProxy Runtime API
  58. # e.g. echo "show table emqx_tcp_back" | sudo socat stdio tcp4-connect:172.100.239.4:9999
  59. stats socket :9999 level admin expose-fd listeners
  60. ##----------------------------------------------------------------
  61. ## defaults
  62. ##----------------------------------------------------------------
  63. defaults
  64. log global
  65. mode tcp
  66. option tcplog
  67. # Replace 1024000 with deployment connections
  68. maxconn 1000
  69. timeout connect 30000
  70. timeout client 600s
  71. timeout server 600s
  72. ##----------------------------------------------------------------
  73. ## API
  74. ##----------------------------------------------------------------
  75. frontend emqx_dashboard
  76. mode tcp
  77. option tcplog
  78. bind *:18083
  79. default_backend emqx_dashboard_back
  80. backend emqx_dashboard_back
  81. # Must use a consistent dispatch when EMQX is running on different versions
  82. # because the js files for the dashboard is chunked, having the backends sharing
  83. # load randomly will cause the browser fail to GET some chunks (or get bad chunks if names clash)
  84. balance source
  85. mode http
  86. server emqx-1 $NODE1:18083
  87. server emqx-2 $NODE2:18083
  88. ##----------------------------------------------------------------
  89. ## TLS
  90. ##----------------------------------------------------------------
  91. frontend emqx_ssl
  92. mode tcp
  93. option tcplog
  94. bind *:8883 ssl crt /tmp/emqx.pem ca-file /usr/local/etc/haproxy/certs/cacert.pem verify required no-sslv3
  95. default_backend emqx_ssl_back
  96. frontend emqx_wss
  97. mode tcp
  98. option tcplog
  99. bind *:8084 ssl crt /tmp/emqx.pem ca-file /usr/local/etc/haproxy/certs/cacert.pem verify required no-sslv3
  100. default_backend emqx_wss_back
  101. backend emqx_ssl_back
  102. mode tcp
  103. balance static-rr
  104. server emqx-1 $NODE1:1883 check-send-proxy send-proxy-v2-ssl-cn
  105. server emqx-2 $NODE2:1883 check-send-proxy send-proxy-v2-ssl-cn
  106. backend emqx_wss_back
  107. mode tcp
  108. balance static-rr
  109. server emqx-1 $NODE1:8083 check-send-proxy send-proxy-v2-ssl-cn
  110. server emqx-2 $NODE2:8083 check-send-proxy send-proxy-v2-ssl-cn
  111. EOF
  112. docker run -d --name haproxy \
  113. --net "$NET" \
  114. -v "$(pwd)/tmp/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg" \
  115. -v "$(pwd)/apps/emqx/etc/certs:/usr/local/etc/haproxy/certs" \
  116. -w /usr/local/etc/haproxy \
  117. -p 18083:18083 \
  118. -p 8883:8883 \
  119. -p 8084:8084 \
  120. "haproxy:2.4" \
  121. bash -c 'set -euo pipefail;
  122. cat certs/cert.pem certs/key.pem > /tmp/emqx.pem;
  123. haproxy -f haproxy.cfg'
  124. wait_limit=60
  125. wait_for_emqx() {
  126. container="$1"
  127. wait_limit="$2"
  128. wait_sec=0
  129. while ! docker exec "$container" emqx ctl status; do
  130. wait_sec=$(( wait_sec + 1 ))
  131. if [ $wait_sec -gt "$wait_limit" ]; then
  132. echo "timeout wait for EMQX"
  133. exit 1
  134. fi
  135. echo -n '.'
  136. sleep 1
  137. done
  138. }
  139. wait_for_haproxy() {
  140. wait_sec=0
  141. wait_limit="$1"
  142. set +x
  143. while ! openssl s_client \
  144. -CAfile apps/emqx/etc/certs/cacert.pem \
  145. -cert apps/emqx/etc/certs/cert.pem \
  146. -key apps/emqx/etc/certs/key.pem \
  147. localhost:8084 </dev/null; do
  148. wait_sec=$(( wait_sec + 1 ))
  149. if [ $wait_sec -gt "$wait_limit" ]; then
  150. echo "timeout wait for haproxy"
  151. exit 1
  152. fi
  153. echo -n '.'
  154. sleep 1
  155. done
  156. }
  157. wait_for_emqx "$NODE1" 30
  158. wait_for_emqx "$NODE2" 30
  159. wait_for_haproxy 10
  160. echo
  161. docker exec $NODE1 emqx ctl cluster join "emqx@$NODE2"