您好——我将严格根据官方 Docker 容器的运行时事实重述此事。
我在运行的容器中看到的情况(事实)
这是一个官方 Docker 安装,带有 runit(标准的 /var/discourse 启动器工作流程;事件发生前没有重建)。在容器内:
- 存在一个 runit Sidekiq 服务,并且是正在被监控的那个
ls -l /etc/service/sidekiq/run
sv status sidekiq
事件期间的输出:
down: sidekiq: 1s, normally up, want up
- 手动启动 Sidekiq 成功
cd /var/www/discourse
sudo -u discourse bundle exec sidekiq -C config/sidekiq.yml
这会保持运行,连接到 Redis,并处理作业。
- 仅修补 /etc/service/sidekiq/run (不重建)立即修复了崩溃循环 将 /etc/service/sidekiq/run 替换为:
#!/bin/bash
exec 2>&1
cd /var/www/discourse
mkdir -p tmp/pids
chown discourse:discourse tmp/pids || true
exec chpst -u discourse:discourse \
bash -lc 'cd /var/www/discourse && rm -f tmp/pids/sidekiq*.pid; exec bundle exec sidekiq -C config/sidekiq.yml'
之后:
sv status sidekiq
run: sidekiq: (pid <PID>) <SECONDS>s
因此,在这个官方镜像中,Sidekiq 不是通过 Unicorn master 启动的;它是一个 runit 服务,其运行时脚本可能会陷入崩溃循环。
为什么您可能看不到确切的代码在
discourse_docker 中
我同意确切的文本可能不在仓库中,因为 /etc/service/sidekiq/run 是在镜像构建/启动期间生成/注入的运行时工件,不一定是 discourse_docker 中逐字对应的文件。但如上所示,它是这个官方镜像中活动的受监控服务。
触发脆弱性的原因(事实 + 最少推断)
- 我们还观察到由于标准的 Debian 权限设置(/var/log = root:adm 0775),logrotate 每天都会失败,因此在添加全局 su root adm 之前,logrotate 拒绝轮换。
- 当 logrotate 失败时,它会在 /shared/log/rails/ 下重新创建文件,包括 sidekiq.log。
- 此镜像中默认的 runit 脚本使用 discourse:www-data 并强制将 -L log/sidekiq.log 写入 /shared/log,这使得 Sidekiq 对共享卷权限漂移非常敏感,并可能在有有用日志之前立即退出。
请求/建议
鉴于以上情况,我们能否考虑加强默认的 Docker/runit Sidekiq 服务?
建议的默认设置:
- 以 discourse:discourse 身份运行(与容器内的典型所有权匹配),
- 通过 bundle exec sidekiq -C config/sidekiq.yml 启动,
- 避免强制共享的 -L log/sidekiq.log(或使其具有弹性)。
这将防止导致所有后台/AI 作业停止的静默的 down: 1s 崩溃循环。
我很乐意测试您指向我的任何分支/提交。