您当前的位置: 首页 >  docker

科技D人生

暂无认证

  • 0浏览

    0关注

    1550博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

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

科技D人生 发布时间:2020-05-29 09:32:03 ,浏览量:0

背景

使用 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

关注
打赏
1662604032
查看更多评论
立即登录/注册

微信扫码登录

0.1808s