Aller au contenu

mkdocs serve ne rechargeait jamais automatiquement — bug Click sur --livereload

Contexte

Le wiki second-memory est exposé via un conteneur Docker mkdocs-wiki (image mkdocs-wiki-custom, basée sur squidfunk/mkdocs-material), avec un bind mount direct /home/kanmaber/second-memory/docs, tournant en continu depuis fin juin. En ajoutant de nouvelles pages au wiki (projet jobPipeline), elles n'apparaissaient pas sur le site tant que le conteneur n'était pas redémarré manuellement.

Contenu

Fausses pistes écartées (vérifiées puis exclues)

  • Montage Docker : vérifié via docker inspect — bind mount direct, même inode côté hôte et conteneur, mtime parfaitement synchronisé. Pas un problème de montage.
  • watchdog absent : vérifié installé (v6.0.0) dans le conteneur.
  • Limites inotify de l'hôte : max_user_watches/max_user_instances largement suffisants, 95 fichiers seulement dans wiki/.
  • Plugin roamlinks ou material/search corrompant l'objet serveur via le hook on_serve (config.plugins.on_serve() réassigne server dans mkdocs/commands/serve.py) : vérifié dans le code source des deux plugins — aucun ne casse la chaîne (le mécanisme run_event de mkdocs garde l'objet original si le hook renvoie None, ce qui est le cas ici).
  • DNSBL/blacklist de l'IP, filtre anti-spam : sans rapport, mauvaise piste initiale abandonnée après vérification.

Cause racine réelle

mkdocs serve utilise en interne watchdog.observers.polling.PollingObserver (pas inotify natif — choix délibéré de mkdocs, visible dans mkdocs/livereload/__init__.py). Le déclenchement de la surveillance dépend du paramètre livereload passé à mkdocs.commands.serve.serve(), lui-même dérivé des options Click :

@click.option('--no-livereload', 'livereload', flag_value=False, help=...)
@click.option('--livereload', 'livereload', flag_value=True, default=True, hidden=True)

Ces deux options partagent la même variable cible (livereload) via flag_value. En instrumentant directement le code (ajout de print() temporaires dans mkdocs/commands/serve.py, confirmé puis fichier restauré à l'identique après diagnostic), la valeur réellement reçue par serve() en l'absence de tout flag explicite sur la ligne de commande était False, alors que la valeur voulue est True. Bug/particularité de Click dans cette version de mkdocs (1.6.1, image datée du 19/03) — pas un problème de configuration côté second-memory.

Conséquence concrète : dans serve.py, le bloc if livereload: server.watch(config.docs_dir) n'était jamais exécuté → aucune surveillance de fichiers active → le site ne se reconstruit qu'une seule fois, au démarrage du conteneur, jamais ensuite.

Méthode de diagnostic (réutilisable pour un bug similaire)

  1. Vérifier d'abord les couches simples : montage, dépendances installées, limites système (inotify), avant de suspecter le code applicatif.
  2. Écarter les plugins un par un en lisant leur code source réel (pas en supposant) — ici deux plugins ont été lus intégralement avant d'être innocentés.
  3. Quand les logs standards ne suffisent pas, instrumenter directement le code source dans le conteneur (docker exec + réécriture du fichier Python avec des print(..., flush=True) ciblés), relancer, lire les traces, puis restaurer le fichier original immédiatement après diagnostic (cp d'une sauvegarde faite avant modification).
  4. Confirmer la cause avec un test empirique reproductible (ici : lancer mkdocs serve -v en verbeux et chercher l'absence du log "Watching paths for changes: ..." qui aurait dû apparaître).

Correctif appliqué

Aucun docker-compose.yml ni service systemd ne pilote ce conteneur — il avait été lancé une fois manuellement. Recréé à l'identique (même image, port 127.0.0.1:3010→8000, volume, --restart unless-stopped), en ajoutant explicitement le flag --livereload à la commande :

docker rm -f mkdocs-wiki
docker run -d \
  --name mkdocs-wiki \
  --restart unless-stopped \
  -p 127.0.0.1:3010:8000 \
  -v /home/kanmaber/second-memory:/docs \
  mkdocs-wiki-custom \
  serve --dev-addr=0.0.0.0:8000 --livereload

Passer le flag explicitement sur la ligne de commande contourne le bug de résolution du défaut, sans toucher au code source de mkdocs.

Vérifié après correctif : les logs affichent désormais au démarrage Watching paths for changes: 'wiki', 'mkdocs.yml', et une modification de fichier test a bien déclenché Detected file changesBuilding documentation...Reloading browsers en quelques secondes.

Décision / Conclusion

Le conteneur mkdocs-wiki recrée avec --livereload explicite est la version en production. Cette note elle-même sert de test en conditions réelles : si elle apparaît sur le site sans redémarrage manuel du conteneur, le correctif est confirmé durablement.

À faire

  • Si un jour le conteneur est recréé depuis une image mise à jour (ou reconstruit depuis le Dockerfile), vérifier qu'une future version de mkdocs ne réintroduit pas ce comportement — retester avec docker logs mkdocs-wiki | grep "Watching paths" après toute recréation.
  • Envisager de documenter la commande de lancement dans un vrai docker-compose.yml versionné (actuellement aucun fichier ne fait autorité sur la commande exacte du conteneur — seule cette note en garde la trace).

Liens connexes