Docker学习总结(50)——Docker 微服务优雅关闭

Docker
个人学习docker的一些历程,分享给大家,供参考,一起学习进步!
科技D人生

背景

使用 docker stop 关闭容器时, 只有 init(pid 1)进程能收到中断信号, 如果容器的pid 1 进程是 sh 进程, 它不具备转发结束信号到它的子进程的能力, 所以我们真正的java程序得不到中断信号, 也就不能实现优雅关闭. 解决思路是: 让pid 1 进程具备转发终止信号, 或者将 java 程序配成 pid 1 进程.需要说明的是, docker stop 默认是等待10秒钟, 这个时间有点太短了, 可以加 -t 参数, 比如 -t 30 等待30秒钟.上面的 Dockerfile 的pid 1是一个 sh 命令,并不能实现优雅关闭, 需要再改进.

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" 形式的命令.

init 进程调整方案

方案1: 自行确保 pid 1 是我们的java程序.
上面的 Dockerfile 可以确保 java 程序作为 pid 1进程.

方案评价: 有时候不太容易将我们的主程序调整为 pid 1 进程, 另外虽然 docker 容器推荐是单进程, 但实际情形往往不是这么理想. 本方案仅仅适合单进程容器.

方案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脚本文件.

改造之前的 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

展开阅读全文
©️2020 CSDN 皮肤主题: 技术黑板 设计师: CSDN官方博客 返回首页
实付39.90元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值