docker 優雅的關閉 spring boot 應用容器

============================
docker 微服務的優雅關閉
============================java

使用 docker stop 關閉容器時, 只有 init(pid 1)進程能收到中斷信號, 若是容器的pid 1 進程是 sh 進程, 它不具有轉發結束信號到它的子進程的能力, 因此咱們真正的java程序得不到中斷信號, 也就不能實現優雅關閉. 解決思路是: 讓pid 1 進程具有轉發終止信號, 或者將 java 程序配成 pid 1 進程.git

須要說明的是, docker stop 默認是等待10秒鐘, 這個時間有點過短了, 能夠加 -t 參數, 好比 -t 30 等待30秒鐘.github

 

----------------------------------
背景知識
----------------------------------docker

上面的 Dockerfile 的pid 1是一個 sh 命令,並不能實現優雅關閉, 須要再改進.shell

 

ENTRYPOINT/CMD 的幾種寫法, 會影響 pid 1 進程的產生:
寫法1:
"shell" format 的 ENTRYPOINT/CMD, 不帶方括號:
ENTRYPOINT top -b
#PID 1 是 /bin/sh -c shell  top -b
#另外有個 pid 7 是 top -b

寫法2:
"shell" format 的 ENTRYPOINT/CMD, 不帶方括號, 但此次ENTRYPOINT後緊跟了一個 exec :
ENTRYPOINT exec top -b
#PID 1 是 top -b

寫法3:
"exec" form 的 ENTRYPOINT/CMD, 方括號括着, 每一個部分都是json字符串.
ENTRYPOINT ["top","-b"]
pid 1 進程就是 top -b

因此推薦使用"exec" form的命令, 而不是 "shell" 形式的命令.json


----------------------------------
init 進程調整方案
----------------------------------
方案1: 自行確保 pid 1 是咱們的java程序.
上面的 Dockerfile 能夠確保 java 程序做爲 pid 1進程.微服務

方案評價: 有時候不太容易將咱們的主程序調整爲 pid 1 進程, 另外雖然 docker 容器推薦是單進程, 但實際情形每每不是這麼理想. 本方案僅僅適合單進程容器.spa

方案2: 適合於 Docker 1.13 以上.
Docker 1.13以上的docker run 命令新增了 --init 參數, 加了該參數後, docker 會啓用 tini 做爲 init (pid 1) 進程, 該 tini 進程可以將終止信號轉發給其子進程, 同時能reap 子進程, 不會出現因孤兒進程致使的線程句柄沒法回收情形.
詳見: https://github.com/krallin/tini線程

 

方案3(推薦): 在docker鏡像中強制 tini 做爲 init(pid 1) 進程, 該方案使用範圍廣, ENTRYPOINT 能夠是任意sh腳本文件.orm

改造以前的 Dockerfile

ENTRYPOINT ["/docker-entrypoint.sh"]

改造後的 Dockerfile

# Add Tini
ENV TINI_VERSION v0.18.0
ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini /tini
RUN chmod +x /tini

ENTRYPOINT ["/usr/local/bin/tini", "--", "/docker-entrypoint.sh"]


tini 文檔:
https://github.com/krallin/tini
有關 docker run --init 參數的說明
http://stackoverflow.com/a/39593409/6309

=============================== 更多推薦 =============================== https://efekahraman.github.io/2018/04/docker-awareness-in-java

相關文章
相關標籤/搜索