Dockerfile 中 CMD 为什么要避免使用 sh -c

CSDN 中文章不一定能及时更新,欢迎点击前往我的博客查看最新版本:许盛的博客

Dockerfile 中的 CMD 命令,有 exec formshell form 两种形式,具体区别可以参考: Dockerfile 中 CMD 写法的区别

推荐使用 exec form 而不是 shell form ,因为使用 exec form 时可以将实际的应用程序作为容器中的主进程,而使用 shell form 时,容器中的主进程实际上是 sh

当我们需要终止一个容器时,需要向这个容器传递 signal ,然后由主进程捕获 signal 并退出。

但是 sh 默认并不会处理 signal(kill 除外) ,在 k8s 集群中终止容器时,会先向其发送 SIGTERM 信号,然后由应用程序响应后自行退出,达到优雅退出的目的。

如果容器的主进程是 sh,那么 sh 接收到信息后,并不会传递给子进程,也不会退出,会导致容器退出失败,等待超时后被 k8s 强制 kill 掉。

可以实践一下进行验证。

exec form 写法

准备一个 Dockerfile 文件,内容如下:

FROM nginx
MAINTAINER https://www.xuxusheng.com
CMD ["nginx", "-g", "daemon off;"]

这种写法就是 exec form,基于此镜像运行的容器内主进程应该为 nginx

再使用如下命令运行一个容器起来。

# 构建镜像
docker build -t my-nginx .

# 运行容器
docker run --name my-nginx my-nginx

可以看到容器正常启动了。

Untitled

再通过命令 docker top my-nginx 可以看到:

Untitled

此时容器中主进程为 nginx

再使用 ps 命令查询到刚才运行的 docker run 命令的 pid

Untitled

如上所示,使用命令 kill -15 <pid> 向其传递 SIGTERM 信号,会发现容器正常退出。

直接在容器运行的终端中使用 ctrl + c 也会正常退出(传递 SIGINT 信号)。

shell form

准备如下 Dockerfile 文件:

FROM nginx
MAINTAINER https://www.xuxusheng.com
CMD nginx -g "daemon off;"

这种写法为 shell form 形式,容器中主进程会变成 sh

重复上一节中的各个步骤,可以看到 docker top 命令输出如下:

Untitled

此时不管是使用 kill -15 <pid> 还是 ctrl + c 方式,会发现容器都无法正常退出。

所以结论是,尽量避免使用 CMDshell form 写法,让容器中的主进程是你的应用程序而不是 sh,避免容器无法正常退出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值