Boucle de crash d'Nginx après redémarrage du conteneur : l'image de base inclut brotli_static dans discourse.conf mais ne charge jamais le module (directive inconnue)

Résumé
Après un redémarrage régulier du conteneur (redémarrage de l’hôte / docker restart), nginx échoue à démarrer dans le conteneur app avec l’erreur suivante :

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

Cela met le site entier hors ligne (aucune solution de repli — nginx ne se lie jamais aux ports 80/443) jusqu’à ce qu’un correctif manuel soit appliqué.

Environnement

  • Image de base : discourse/base:2.0.20260812-0036
  • nginx : 1.26.3-3+deb13u7 (paquet Debian 13/trixie, non compilé sur mesure)
  • libnginx-mod-http-brotli-static/-filter 1.0.0~rc-6 sont installés, et les liens symboliques /etc/nginx/mods-enabled/*.conf (avec les lignes load_module correctes) existent et pointent vers des fichiers .so valides.

Cause racine
/etc/nginx/nginx.conf (appartenant au paquet nginx-common, non modifié) ne contient pas la directive include /etc/nginx/modules-enabled/*.conf;, de sorte que les modules Brotli installés ne sont jamais chargés — tandis que discourse.conf (généré par les modèles Discourse) émet toujours brotli_static on; en supposant qu’ils le sont.

Pourquoi l’échec n’est pas immédiat
La configuration n’est réanalysée que lorsque nginx redémarre réellement. Un conteneur nouvellement reconstruit peut fonctionner correctement pendant des jours ou des semaines jusqu’à ce que quelque chose redémarre nginx (redémarrage de l’hôte, docker restart, OOM, etc.), moment où il commence à boucler silencieusement sur les erreurs (~1 fois/seconde) sans récupération automatique.

Contournement
Ajouter include /etc/nginx/modules-enabled/*.conf; comme première ligne de /etc/nginx/nginx.conf (contexte principal, avant events {}). Cela a permis de confirmer le retour à un état de succès de nginx -t et un fonctionnement normal.

Demande
Le paquet d’image de base pourrait-il soit (a) ajouter cet include à son nginx.conf, soit (b) supprimer brotli_static/brotli du modèle discourse.conf fourni si la construction du paquet nginx de la distribution n’inclut plus le support Brotli par défaut ?

2 « J'aime »

Correction de mon rapport : l’image de base est saine. La cause était locale à notre installation.

Ce qui s’est réellement passé

Un job cron local sur notre hôte copie des fichiers de configuration nginx obsolètes, maintenus manuellement, dans le conteneur en cours d’exécution. L’un d’entre eux est antérieur à include /etc/nginx/modules-enabled/*.conf;, et l’autre définit toujours brotli_static on;. Ensemble, ils génèrent l’erreur unknown directive "brotli_static", et nginx refuse de démarrer.

Pourquoi je l’ai mal diagnostiqué

J’ai inspecté /etc/nginx/nginx.conf dans le conteneur en cours d’exécution et j’ai constaté que l’inclusion modules-enabled manquait. Ce fichier avait déjà été écrasé localement, de sorte que le conteneur en cours d’exécution ne reflétait jamais ce que Discourse génère réellement. L’inspection de l’image construite rend la situation évidente. L’inclusion est bien présente :

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

Pourquoi le problème n’est apparu qu’avec un délai

Ceci peut être la partie utile pour les autres. Le job se termine par nginx -s reload et ignore sa sortie. Lorsque la configuration est cassée, le rechargement échoue silencieusement et le nginx en cours d’exécution continue de servir à partir de sa configuration déjà chargée. Tout semble en bon état. La défaillance ne devient visible qu’au prochain vrai démarrage de nginx, qui, dans notre cas, a été un redémarrage de l’hôte suite à une mise à niveau non supervisée du noyau quelques jours plus tard.

Ainsi, si un conteneur Discourse a servi du trafic sans problème et meurt ensuite lors d’un redémarrage sans rapport, vérifiez si quelque chose n’a pas écrasé sa configuration nginx entre-temps.

Mes excuses pour le bruit, et merci à ceux qui ont pris le temps d’examiner cela.

1 « J'aime »