docker.sh 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. #!/usr/bin/env sh
  2. #DEPLOY_DOCKER_CONTAINER_LABEL="xxxxxxx"
  3. #DEPLOY_DOCKER_CONTAINER_KEY_FILE="/path/to/key.pem"
  4. #DEPLOY_DOCKER_CONTAINER_CERT_FILE="/path/to/cert.pem"
  5. #DEPLOY_DOCKER_CONTAINER_CA_FILE="/path/to/ca.pem"
  6. #DEPLOY_DOCKER_CONTAINER_FULLCHAIN_FILE="/path/to/fullchain.pem"
  7. #DEPLOY_DOCKER_CONTAINER_RELOAD_CMD="service nginx force-reload"
  8. _DEPLOY_DOCKER_WIKI="https://github.com/Neilpang/acme.sh/wiki/deploy-to-docker-containers"
  9. _DOCKER_HOST_DEFAULT="/var/run/docker.sock"
  10. docker_deploy() {
  11. _cdomain="$1"
  12. _ckey="$2"
  13. _ccert="$3"
  14. _cca="$4"
  15. _cfullchain="$5"
  16. _debug _cdomain "$_cdomain"
  17. _getdeployconf DEPLOY_DOCKER_CONTAINER_LABEL
  18. _debug2 DEPLOY_DOCKER_CONTAINER_LABEL "$DEPLOY_DOCKER_CONTAINER_LABEL"
  19. if [ -z "$DEPLOY_DOCKER_CONTAINER_LABEL" ]; then
  20. _err "The DEPLOY_DOCKER_CONTAINER_LABEL variable is not defined, we use this label to find the container."
  21. _err "See: $_DEPLOY_DOCKER_WIKI"
  22. fi
  23. _savedeployconf DEPLOY_DOCKER_CONTAINER_LABEL "$DEPLOY_DOCKER_CONTAINER_LABEL"
  24. if [ "$DOCKER_HOST" ]; then
  25. _saveaccountconf DOCKER_HOST "$DOCKER_HOST"
  26. fi
  27. if _exists docker && docker version | grep -i docker >/dev/null; then
  28. _info "Using docker command"
  29. export _USE_DOCKER_COMMAND=1
  30. else
  31. export _USE_DOCKER_COMMAND=
  32. fi
  33. export _USE_UNIX_SOCKET=
  34. if [ -z "$_USE_DOCKER_COMMAND" ]; then
  35. export _USE_REST=
  36. if [ "$DOCKER_HOST" ]; then
  37. _debug "Try use docker host: $DOCKER_HOST"
  38. export _USE_REST=1
  39. else
  40. export _DOCKER_SOCK="$_DOCKER_HOST_DEFAULT"
  41. _debug "Try use $_DOCKER_SOCK"
  42. if [ ! -e "$_DOCKER_SOCK" ] || [ ! -w "$_DOCKER_SOCK" ]; then
  43. _err "$_DOCKER_SOCK is not available"
  44. return 1
  45. fi
  46. export _USE_UNIX_SOCKET=1
  47. if ! _exists "curl"; then
  48. _err "Please install curl first."
  49. _err "We need curl to work."
  50. return 1
  51. fi
  52. if ! _check_curl_version; then
  53. return 1
  54. fi
  55. fi
  56. fi
  57. _getdeployconf DEPLOY_DOCKER_CONTAINER_KEY_FILE
  58. _debug2 DEPLOY_DOCKER_CONTAINER_KEY_FILE "$DEPLOY_DOCKER_CONTAINER_KEY_FILE"
  59. if [ "$DEPLOY_DOCKER_CONTAINER_KEY_FILE" ]; then
  60. _savedeployconf DEPLOY_DOCKER_CONTAINER_KEY_FILE "$DEPLOY_DOCKER_CONTAINER_KEY_FILE"
  61. fi
  62. _getdeployconf DEPLOY_DOCKER_CONTAINER_CERT_FILE
  63. _debug2 DEPLOY_DOCKER_CONTAINER_CERT_FILE "$DEPLOY_DOCKER_CONTAINER_CERT_FILE"
  64. if [ "$DEPLOY_DOCKER_CONTAINER_CERT_FILE" ]; then
  65. _savedeployconf DEPLOY_DOCKER_CONTAINER_CERT_FILE "$DEPLOY_DOCKER_CONTAINER_CERT_FILE"
  66. fi
  67. _getdeployconf DEPLOY_DOCKER_CONTAINER_CA_FILE
  68. _debug2 DEPLOY_DOCKER_CONTAINER_CA_FILE "$DEPLOY_DOCKER_CONTAINER_CA_FILE"
  69. if [ "$DEPLOY_DOCKER_CONTAINER_CA_FILE" ]; then
  70. _savedeployconf DEPLOY_DOCKER_CONTAINER_CA_FILE "$DEPLOY_DOCKER_CONTAINER_CA_FILE"
  71. fi
  72. _getdeployconf DEPLOY_DOCKER_CONTAINER_FULLCHAIN_FILE
  73. _debug2 DEPLOY_DOCKER_CONTAINER_FULLCHAIN_FILE "$DEPLOY_DOCKER_CONTAINER_FULLCHAIN_FILE"
  74. if [ "$DEPLOY_DOCKER_CONTAINER_FULLCHAIN_FILE" ]; then
  75. _savedeployconf DEPLOY_DOCKER_CONTAINER_FULLCHAIN_FILE "$DEPLOY_DOCKER_CONTAINER_FULLCHAIN_FILE"
  76. fi
  77. _getdeployconf DEPLOY_DOCKER_CONTAINER_RELOAD_CMD
  78. _debug2 DEPLOY_DOCKER_CONTAINER_RELOAD_CMD "$DEPLOY_DOCKER_CONTAINER_RELOAD_CMD"
  79. if [ "$DEPLOY_DOCKER_CONTAINER_RELOAD_CMD" ]; then
  80. _savedeployconf DEPLOY_DOCKER_CONTAINER_RELOAD_CMD "$DEPLOY_DOCKER_CONTAINER_RELOAD_CMD"
  81. fi
  82. _cid="$(_get_id "$DEPLOY_DOCKER_CONTAINER_LABEL")"
  83. _info "Container id: $_cid"
  84. if [ -z "$_cid" ]; then
  85. _err "can not find container id"
  86. return 1
  87. fi
  88. if [ "$DEPLOY_DOCKER_CONTAINER_KEY_FILE" ]; then
  89. if ! _docker_cp "$_cid" "$_ckey" "$DEPLOY_DOCKER_CONTAINER_KEY_FILE"; then
  90. return 1
  91. fi
  92. fi
  93. if [ "$DEPLOY_DOCKER_CONTAINER_CERT_FILE" ]; then
  94. if ! _docker_cp "$_cid" "$_ccert" "$DEPLOY_DOCKER_CONTAINER_CERT_FILE"; then
  95. return 1
  96. fi
  97. fi
  98. if [ "$DEPLOY_DOCKER_CONTAINER_CA_FILE" ]; then
  99. if ! _docker_cp "$_cid" "$_cca" "$DEPLOY_DOCKER_CONTAINER_CA_FILE"; then
  100. return 1
  101. fi
  102. fi
  103. if [ "$DEPLOY_DOCKER_CONTAINER_FULLCHAIN_FILE" ]; then
  104. if ! _docker_cp "$_cid" "$_cfullchain" "$DEPLOY_DOCKER_CONTAINER_FULLCHAIN_FILE"; then
  105. return 1
  106. fi
  107. fi
  108. if [ "$DEPLOY_DOCKER_CONTAINER_RELOAD_CMD" ]; then
  109. _info "Reloading: $DEPLOY_DOCKER_CONTAINER_RELOAD_CMD"
  110. if ! _docker_exec "$_cid" "$DEPLOY_DOCKER_CONTAINER_RELOAD_CMD"; then
  111. return 1
  112. fi
  113. fi
  114. return 0
  115. }
  116. #label
  117. _get_id() {
  118. _label="$1"
  119. if [ "$_USE_DOCKER_COMMAND" ]; then
  120. docker ps -f label="$_label" --format "{{.ID}}"
  121. elif [ "$_USE_REST" ]; then
  122. _err "Not implemented yet."
  123. return 1
  124. elif [ "$_USE_UNIX_SOCKET" ]; then
  125. _req="{\"label\":[\"$_label\"]}"
  126. _debug2 _req "$_req"
  127. _req="$(printf "%s" "$_req" | _url_encode)"
  128. _debug2 _req "$_req"
  129. listjson="$(_curl_unix_sock "${_DOCKER_SOCK:-$_DOCKER_HOST_DEFAULT}" GET "/containers/json?filters=$_req")"
  130. _debug2 "listjson" "$listjson"
  131. echo "$listjson" | tr '{,' '\n' | grep -i '"id":' | _head_n 1 | cut -d '"' -f 4
  132. else
  133. _err "Not implemented yet."
  134. return 1
  135. fi
  136. }
  137. #id cmd
  138. _docker_exec() {
  139. _eargs="$*"
  140. _debug2 "_docker_exec $_eargs"
  141. _dcid="$1"
  142. shift
  143. if [ "$_USE_DOCKER_COMMAND" ]; then
  144. docker exec -i "$_dcid" sh -c "$*"
  145. elif [ "$_USE_REST" ]; then
  146. _err "Not implemented yet."
  147. return 1
  148. elif [ "$_USE_UNIX_SOCKET" ]; then
  149. _cmd="$*"
  150. #_cmd="$(printf "%s" "$_cmd" | sed 's/ /","/g')"
  151. _debug2 _cmd "$_cmd"
  152. #create exec instance:
  153. cjson="$(_curl_unix_sock "$_DOCKER_SOCK" POST "/containers/$_dcid/exec" "{\"Cmd\": [\"sh\", \"-c\", \"$_cmd\"]}")"
  154. _debug2 cjson "$cjson"
  155. execid="$(echo "$cjson" | cut -d '"' -f 4)"
  156. _debug execid "$execid"
  157. ejson="$(_curl_unix_sock "$_DOCKER_SOCK" POST "/exec/$execid/start" "{\"Detach\": false,\"Tty\": false}")"
  158. _debug2 ejson "$ejson"
  159. if [ "$ejson" ]; then
  160. _err "$ejson"
  161. return 1
  162. fi
  163. else
  164. _err "Not implemented yet."
  165. return 1
  166. fi
  167. }
  168. #id from to
  169. _docker_cp() {
  170. _dcid="$1"
  171. _from="$2"
  172. _to="$3"
  173. _info "Copying file from $_from to $_to"
  174. _dir="$(dirname "$_to")"
  175. _debug2 _dir "$_dir"
  176. if ! _docker_exec "$_dcid" mkdir -p "$_dir"; then
  177. _err "Can not create dir: $_dir"
  178. return 1
  179. fi
  180. if [ "$_USE_DOCKER_COMMAND" ]; then
  181. if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then
  182. _docker_exec "$_dcid" tee "$_to" <"$_from"
  183. else
  184. _docker_exec "$_dcid" tee "$_to" <"$_from" >/dev/null
  185. fi
  186. if [ "$?" = "0" ]; then
  187. _info "Success"
  188. return 0
  189. else
  190. _info "Error"
  191. return 1
  192. fi
  193. elif [ "$_USE_REST" ]; then
  194. _err "Not implemented yet."
  195. return 1
  196. elif [ "$_USE_UNIX_SOCKET" ]; then
  197. _frompath="$_from"
  198. if _startswith "$_frompath" '/'; then
  199. _frompath="$(echo "$_from" | cut -b 2-)" #remove the first '/' char
  200. fi
  201. _debug2 "_frompath" "$_frompath"
  202. _toname="$(basename "$_to")"
  203. _debug2 "_toname" "$_toname"
  204. _debug2 "_from" "$_from"
  205. if ! tar --transform="s,$(printf "%s" "$_frompath" | tr '*' .),$_toname," -cz "$_from" 2>/dev/null | _curl_unix_sock "$_DOCKER_SOCK" PUT "/containers/$_dcid/archive?noOverwriteDirNonDir=1&path=$(printf "%s" "$_dir" | _url_encode)" '@-' "Content-Type: application/octet-stream"; then
  206. _err "copy error"
  207. return 1
  208. fi
  209. return 0
  210. else
  211. _err "Not implemented yet."
  212. return 1
  213. fi
  214. }
  215. #sock method endpoint data content-type
  216. _curl_unix_sock() {
  217. _socket="$1"
  218. _method="$2"
  219. _endpoint="$3"
  220. _data="$4"
  221. _ctype="$5"
  222. if [ -z "$_ctype" ]; then
  223. _ctype="Content-Type: application/json"
  224. fi
  225. _debug _data "$_data"
  226. _debug2 "url" "http://localhost$_endpoint"
  227. if [ "$_CURL_NO_HOST" ]; then
  228. _cux_url="http:$_endpoint"
  229. else
  230. _cux_url="http://localhost$_endpoint"
  231. fi
  232. if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then
  233. curl -vvv --silent --unix-socket "$_socket" -X "$_method" --data-binary "$_data" --header "$_ctype" "$_cux_url"
  234. else
  235. curl --silent --unix-socket "$_socket" -X "$_method" --data-binary "$_data" --header "$_ctype" "$_cux_url"
  236. fi
  237. }
  238. _check_curl_version() {
  239. _cversion="$(curl -V | grep '^curl ' | cut -d ' ' -f 2)"
  240. _debug2 "_cversion" "$_cversion"
  241. _major="$(_getfield "$_cversion" 1 '.')"
  242. _debug2 "_major" "$_major"
  243. _minor="$(_getfield "$_cversion" 2 '.')"
  244. _debug2 "_minor" "$_minor"
  245. if [ "$_major$_minor" -lt "740" ]; then
  246. _err "curl v$_cversion doesn't support unit socket"
  247. return 1
  248. fi
  249. if [ "$_major$_minor" -lt "750" ]; then
  250. _debug "Use short host name"
  251. export _CURL_NO_HOST=1
  252. else
  253. export _CURL_NO_HOST=
  254. fi
  255. return 0
  256. }