这一切都从这篇关于在 docker 中设置 nginx 和 certbot 的文章开始。在手册的最后,作者使用以下命令为 nginx 进行了自动证书更新:
command: "/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"
Run Code Online (Sandbox Code Playgroud)
我不是唯一一个不理解这部分的人,所以有一个问题:Why do sleep & wait in bash?
得到的答案是原始命令并不完美,这是更正后的版本:
/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)
但在这个命令中我看到nginx -g \"daemon off;\" &
为什么我们首先将 nginx 放在前台然后将其放入后台?有什么影响?为什么不首先在后台启动 nginx?
另一个问题:据我了解,while
与原始命令不同,该周期保留在 docker 的前台。但是如果nginx if后台,是否意味着它死了,docker不在乎?前台while
仍在工作,没问题。
最后一个问题:为什么在这个命令中有时我们会看到$${!}
,有时会看到${!}
. ${!}
来自同一问题的示例:
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)
我知道这是一个角色逃跑,但我不明白这种情况的规则。
但在这个命令中我看到 nginx -g \"daemon off;\" & 为什么我们首先将 nginx 放在前台,然后将其放入后台?有什么影响?为什么不首先在后台启动 nginx?
原因主要是为了突出差异,并无任何暗示。该命令相当于:
"/bin/sh -c 'nginx; trap exit TERM; while :; do sleep 6h & wait $${!}; nginx -s reload; done'
Run Code Online (Sandbox Code Playgroud)
另一个问题:据我了解,与原始命令不同,while 循环保留在 docker 的前台。但是如果nginx if后台,是否意味着它死了,docker不在乎?在前台仍在工作时,没问题。
该命令基本上创建三个进程:shell 进程 ( /bin/sh
)sleep 6H
和nginx
服务器。第四个进程 ( nginx -s reload
) 每 6 小时分叉一次。Docker 始终监视进程,PID 1
在本例中是 shell ( /bin/sh
)。如果外壳死亡,容器就会退出。如果nginx
作为 shell 进程子进程的服务器死掉了,docker 确实不在乎。
“更正”的版本没有解决这些问题。它与原来的问题相同。SO 问题的答案仅强调除非您想及时处理信号,否则不需要sleep
和。wait
代表着:
"/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx ..."
Run Code Online (Sandbox Code Playgroud)
执行与以下完全相同的操作:
"/bin/sh -c 'while :; do sleep 6h; nginx ..."
Run Code Online (Sandbox Code Playgroud)
总之,正确的实现应该nginx
是主进程 ( PID 1
) 和在后台运行的另一个进程每 6 小时醒来一次,以通知服务器重新加载配置。原始命令和更正后的命令都没有正确实现所有这些。
要解决前面提到的问题,命令应如下所示:
'while :; do sleep 6h; nginx -s reload; done & exec nginx -g "daemon off;"'
Run Code Online (Sandbox Code Playgroud)
系统exec
调用将 shell 进程的内容替换为服务器,nginx
使nginx
主进程处于前台。所有信号现在都正确传播到服务器(另请参阅控制 nginx)。
注意:这个解决方案仍然有一个缺陷。shell 进程(while 循环)不受监控。如果由于任何原因该进程退出,docker 唯一要做的就是发送警报。
希望这能带来一些启发。
归档时间: |
|
查看次数: |
8518 次 |
最近记录: |