在 Docker 中运行时如何触发 nginx 重新加载?当指定 daemon off 时,不会创建 nginx.pid

问题描述 投票:0回答:1

背景

我们使用 nginx 作为 docker compose 堆栈中的反向代理。 nginx 源自 nginx:1.25

我们需要强制 nginx 反向代理重新加载,作为 CI/CD 的一部分

无法保证 docker compose 在重新加载服务容器时会分配相同的 IP 地址,并且 nginx 在启动时缓存名称查找。最终结果是,当我们推送更新时,重新启动的容器最终可能会与反向代理断开连接(这不是理论上的,我们肯定会看到它发生)。

所以我们需要强制 nginx 刷新它的 dns 缓存 - 我们真的不希望反弹整个 nginx 容器。

我想做的是 bash 进入正在运行的容器并运行“service nginx reload”(这是我能找到的所有 nginx 资源所说的要做的事情)。

但是,基于 docker 的 nginx 镜像必须具有 CMD = nginx -g 'daemon off;' (否则容器将会退出)。

问题

当 nginx 在守护进程关闭的情况下启动时,它似乎不会生成 /var/run/nginx.pid 文件。这意味着所有重新加载的尝试都会失败。

其他发现

nginx.conf 文件具有:

pid /var/run/nginx.pid;
- 容器启动后 /var/run 文件夹存在。

真正有趣的是,如果我们执行“service nginx restart”,它会生成 pid 文件,并且从该点开始的所有重新加载都会成功(直到容器重新启动)。

当我们尝试使用非服务命令时,我们会看到类似的行为:

nginx -s reload

结果是:

nginx: [error] open() "/var/run/nginx.pid" failed (2: No such file or directory)

我们在 logrotate.d 上看到了类似的问题 - 它依赖于创建 nginx.pid - 这绝对不会在 -g 'daemon off;' 时发生。发射。

那么:我们如何让 nginx 重新加载而无需重新启动 nginx(或整个容器重新启动)?还是最好的做法是重新启动?

可能(不是很好)的解决方法

我已经尝试过:

docker compose kill -s HUP <nginx_service_name>

这确实会强制重新加载配置 - 但它并不能解决 logrotate 问题(并且无法在不知道 pid 的情况下从容器内的 cron 作业执行kill -s USR1)。

另外,我越来越怀疑重新加载是否足以让 nginx 获取 DNS 更改......也许这里需要重新启动。

与此同时,我正在对 CICD 和 logrotate 配置使用重启。只是希望有一些更手术的东西。

docker nginx nginx-reverse-proxy
1个回答
0
投票

如果其他人遇到这种情况:

根本问题是我使用

docker compose run
而不是
docker compose exec
执行“重新加载”步骤。这会导致操作系统干净启动(不执行 CMD),因此当然不会创建 pid 文件。吸取教训。

另外,我已经确认 nginx -s reload 足以让 nginx 重新加载其 DNS 缓存。无需完全重启。

最终结果是将此调用添加到我的 CICD 脚本中(相当于针对 nginx pid 的kill -s USR1):

docker compose exec <nginx-service-name> nginx -s reload

类似地,在 logrotate 的后轮换中执行以下操作(相当于针对 nginx pid 执行kill -s HUP):

nginx -s reopen
© www.soinside.com 2019 - 2024. All rights reserved.