我在理解docker-compose.yml中服务的启动命令时遇到了麻烦。.yml中的两个相关行是:
command: "/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"
Run Code Online (Sandbox Code Playgroud)
和
entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"
Run Code Online (Sandbox Code Playgroud)
为什么将sleep命令发送到后台然后等待呢?为什么不直接做sleep 6h呢?另外,双美元符号只是逃脱了美元符号${!}吗?
我正在寻找将睡眠和等待结合使用的其他地方,但是似乎没有任何关于原因的解释:
当有人想及时处理信号时,在背景中睡觉然后等待是有意义的。
当bash在前台执行外部命令时,它不会处理任何接收到的信号,直到前台进程终止
(此处详细说明)。
尽管第二个示例实现了信号处理程序,但对于第一个示例,休眠是否在前台执行都没有区别。没有陷阱,信号也不会传播到该nginx过程。为了使其响应SIGTERM信号,入口点应该是这样的:
/bin/sh -c 'nginx -g \"daemon off;\" & trap exit TERM; while :; do sleep 6h & wait $${!}; nginx -s reload; done'
Run Code Online (Sandbox Code Playgroud)
要测试它:
docker run --name test --rm --entrypoint="/bin/sh" nginx -c 'nginx -g "daemon off;" & trap exit TERM; while :; do sleep 20 & wait ${!}; echo running; done'
Run Code Online (Sandbox Code Playgroud)
停止容器
docker stop test
Run Code Online (Sandbox Code Playgroud)
或发送TERM信号(如果主进程未退出,则docker stop发送一个TERM后跟KILL)
docker kill --signal=SIGTERM test
Run Code Online (Sandbox Code Playgroud)
这样,脚本立即退出。现在,如果我们删除wait ${!}陷阱,则在sleep结束时执行陷阱。所有这些对于第二个示例也都适用。
注意:在这两种情况下,其目的都是每12h检查一次证书更新,并每6h重新加载配置,如指南中所述。 这两个命令都可以。恕我直言,第一个示例中的额外等待只是开发人员的疏忽。
编辑:
上面的合理化似乎是为了提供背景睡眠的可能原因,可能会造成一些混乱。(有一篇相关的文章为什么在docker的后台使用nginx和“ daemon off”?)。
尽管上面答案中建议的命令是对问题中命令的改进,但它仍然存在缺陷,因为如链接文章中所述,nginx服务器应该是主要进程,而不是子进程。使用exec系统调用可以轻松实现。脚本变为:
'while :; do sleep 6h; nginx -s reload; done & exec nginx -g "daemon off;"'
Run Code Online (Sandbox Code Playgroud)
(在部分更多信息配置应用程序作为PID 1中泊坞最佳实践)
恕我直言,这种方法要好得多,因为不仅可以nginx监视而且还可以处理信号。nginx -s reload例如,还可以通过简单地将HUP信号发送到docker容器来手动完成配置重载()(请参阅控制nginx)。
| 归档时间: |
|
| 查看次数: |
541 次 |
| 最近记录: |