コンテナ再起動後にNginxがクラッシュループ: ベースイメージのdiscourse.confにbrotli_staticが含まれるがモジュールが読み込まれず(unknown directive)

概要
ルーチンのコンテナ再起動(ホスト再起動 / docker restart)後、app コンテナ内の nginx が以下のエラーで起動に失敗します:

nginx: [emerg] unknown directive "brotli_static" in /etc/nginx/conf.d/discourse.conf:172

これにより、手動でパッチを適用するまでサイト全体がダウンします(フォールバックなし — nginx は 80/443 ポートにバインドされません)。

環境

  • ベースイメージ: discourse/base:2.0.20260812-0036
  • nginx: 1.26.3-3+deb13u7(Debian 13/trixie パッケージ、カスタムコンパイルではありません)
  • libnginx-mod-http-brotli-static/-filter 1.0.0~rc-6 がインストールされており、/etc/nginx/mods-enabled/*.conf のシンボリックリンク(正しい load_module 行を含む)が存在し、有効な .so ファイルを指しています。

根本原因
/etc/nginx/nginx.confnginx-common パッケージが所有、未変更)には include /etc/nginx/modules-enabled/*.conf; ディレクティブが含まれていないため、インストールされた Brotli モジュールは読み込まれません。一方、discourse.conf(Discourse テンプレートによって生成)は、モジュールが読み込まれていることを前提として brotli_static on; を出力し続けています。

なぜ即座に失敗しないのか
設定は nginx が実際に(再)起動したときにのみ再解析されます。新しく再構築されたコンテナは、何らかの要因(ホスト再起動、docker restart、OOM など)で nginx が再起動されるまで、数日から数週間正常に動作し続ける可能性があります。その時点で、自動復旧なしにサイレントにクラッシュループ(約1回/秒)を開始します。

ワークアラウンド
/etc/nginx/nginx.conf の先頭行(メインコンテキスト、events {} の前)に include /etc/nginx/modules-enabled/*.conf; を追加してください。これにより nginx -t が成功し、正常な動作が復旧することが確認されています。

依頼
ベースイメージの nginx.conf にこの include を追加するか、ディストリビューションの nginx パッケージビルドがデフォルトで Brotli サポートをバンドルしなくなった場合、同梱の discourse.conf テンプレートから brotli_static/brotli を削除するかのいずれかに対応していただけますか?

「いいね!」 2

自分のレポートの訂正です:ベースイメージには問題ありません。原因は私たちのインストール環境局所的なものでした。

実際に何が起きたか

ホスト上のローカル cron ジョブが、古い手動管理の nginx 設定ファイルを稼働中のコンテナにコピーしていました。そのうちの一つは include /etc/nginx/modules-enabled/*.conf; が追加される以前のもので、もう一つは依然として brotli_static on; を設定しています。これらが組み合わさることで unknown directive "brotli_static" エラーが発生し、nginx は起動を拒否しました。

なぜ誤診したのか

稼働中のコンテナ内の /etc/nginx/nginx.conf を検査し、modules-enabled の include が欠落していることに気づきました。そのファイルはすでにローカルで上書きされていたため、稼働中のコンテナは Discourse が実際に生成する内容と一致していませんでした。代わりにビルドされたイメージを確認すれば、include が存在していることが明白です。

docker create --name check local_discourse/app
docker cp check:/etc/nginx/nginx.conf ./
docker rm check

なぜ遅れて発覚したのか

これは他の人にとって有用な部分かもしれません。このジョブは nginx -s reload で終了し、その出力を破棄します。設定が壊れている場合、リロードはサイレントに失敗し、稼働中の nginx はすでにロード済みの設定から引き続きサービスを提供し続けます。すべて正常に見えるのです。問題が可視化されるのは、次の実際の nginx 起動時です。私たちの場合、それは数日後にホストを再起動した無人のカーネルアップグレードのタイミングでした。

したがって、Discourse コンテナが正常にトラフィックを処理していたのに、無関係な再起動で停止した場合、その間に nginx 設定が何らかの要因で上書きされていないか確認してください。

騒ぎをすみませんでした。この問題に時間を割いてくださった方々に感謝します。

「いいね!」 1