【问题标题】:Why use nginx with "daemon off" in background with docker?为什么在docker的后台使用带有“守护进程关闭”的nginx?
【发布时间】:2019-12-24 13:16:33
【问题描述】:

这一切都从article 开始,关于在 docker 中设置 nginx 和 certbot。在手册的最后作者使用以下命令为 nginx 自动更新证书:

command: "/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"

我不是唯一不了解这部分的人,所以有一个关于SO的问题: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'

但是在这个命令中我看到nginx -g \"daemon off;\" & 为什么我们先把 nginx 放在前台,然后把它塞到后台呢?有什么影响,为什么不首先在后台启动 nginx?

另一个问题:据我了解,与原始命令不同,while 循环停留在 docker 的前台。但是如果nginx如果是后台,是不是就意味着如果死掉了,docker就不管了?在前台while 还在工作,没问题。

最后一个问题:为什么在这个命令中有时会看到$${!},有时会看到${!}。来自同一个 SO 问题的${!} 示例:

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'

我知道这是一个字符转义,但我不知道这种情况的规则。

【问题讨论】:

    标签: bash docker nginx


    【解决方案1】:

    但是在这个命令中我看到 nginx -g \"daemon off;\" & 为什么我们先把 nginx 放在前台,然后把它塞到后台?有什么影响,为什么不首先在后台启动 nginx?

    原因主要是为了突出差异,没有任何含义。该命令相当于:

    "/bin/sh -c 'nginx; trap exit TERM; while :; do sleep 6h  & wait $${!}; nginx -s reload; done'
    

    另一个问题:据我了解,与原始命令不同,while 循环停留在 docker 的前台。但是如果nginx如果是后台,是不是就意味着如果死掉了,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 ..."
    

    与以下内容完全相同:

    "/bin/sh -c 'while :; do sleep 6h; nginx ..."
    

    总之,一个正确的实现应该将nginx 作为主进程(PID 1),另一个在后台运行的进程每 6 小时唤醒一次以向服务器发出重新加载配置的信号。原始命令和更正后的命令都不能正确实现所有这些。

    要解决前面提到的问题,命令应该是这样的:

    'while :; do sleep 6h; nginx -s reload; done & exec nginx -g "daemon off;"'
    

    exec 系统调用将 shell 进程的内容替换为 nginx 服务器,使 nginx 成为前台的主进程。 现在所有信号都正确传播到服务器(另请参阅Controlling nginx)。

    注意:此解决方案仍有缺陷。不监视 shell 进程(while 循环)。如果出于任何原因,这个进程退出了 docker 唯一做的事情 是发送警报。

    希望这能有所启发。

    【讨论】:

      【解决方案2】:

      回答我关于${!} 和$${!} 的最后一个问题: 显然,如果我们在 docker-compose 文件中用一个美元符号 (${!}) 编写命令,它将被 docker-compose 扩展为“相对于启动 docker-compose 的 shell 的最后一个后台命令的 pid”。因此,容器中的入口点将如下所示:

      /bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait someUnknownLastPID; done;'"
      

      使用$${!},美元符号在 docker-compose 处理中被转义。容器中的入口点将类似于

      /bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait ${!}; done;'"
      

      来源:https://stackoverflow.com/a/40621373/11931043

      【讨论】:

        猜你喜欢
        • 2017-12-04
        • 2015-02-27
        • 2014-11-16
        • 1970-01-01
        • 2023-01-09
        • 1970-01-01
        • 1970-01-01
        • 2017-10-28
        • 1970-01-01
        相关资源
        最近更新 更多