mercure 服务未启用导致 /.well-known/mercure 返回 404,需确认 caddyfile 中未注释的 mercure 块包含完整 publisher_jwt 和 subscriber_jwt 密钥,并在 docker 启动时传入对应环境变量,同时验证 caddy 插件已加载且日志显示 enabled mercure module。

Mercure Hub 的 /.well-known/mercure 返回 404,说明 FrankenPHP 根本没启用 Mercure 服务,不是密钥错、也不是 URL 拼错,而是服务压根没起来。
确认 Caddyfile 中 mercure 块未被注释且参数完整
FrankenPHP 镜像默认禁用 Mercure,必须显式配置。Caddyfile 里必须存在未注释的 mercure 段,且至少包含两个 JWT 密钥:
-
publisher_jwt和subscriber_jwt不能缺失,值可相同但不能为空字符串 - 常见错误:只写了
publisher_jwt,漏掉subscriber_jwt;或密钥用了空格、换行、中文引号 - 路径无关——Mercure 不依赖
root或php_server配置,它由 Caddy 插件独立启动
检查 Docker 启动时是否传入对应环境变量
即使 Caddyfile 写对了,Docker 运行时没传环境变量,Mercure 仍不会加载:
- 必须传入
-e MERCURE_PUBLISHER_JWT_KEY=xxx和-e MERCURE_SUBSCRIBER_JWT_KEY=xxx - 变量名严格区分大小写,
PUBLISHER不是PUBLISHER,SUBSCRIBER不能拼成SUBSCRIBER - 若用
docker-compose.yml,确保environment:下两项都存在,且没被 YAML 注释符号#意外屏蔽
用 curl 直接测 Mercure 端点,别绕过容器网络
在宿主机执行 curl -v http://localhost/.well-known/mercure 是错的——它测的是宿主机 localhost,不是容器内服务:
- 正确做法:进容器执行
curl -v http://localhost:8080/.well-known/mercure(FrankenPHP 默认监听 8080) - 或者从另一个容器(如 busybox)执行
curl -v http://frankenphp:8080/.well-known/mercure,确认服务可跨容器访问 - 返回 200 + JSON 表示正常;404 说明 Caddy 没加载 Mercure 插件;500 通常因 JWT 解析失败(密钥格式非法或为空)
验证 Caddy 是否识别 mercure 指令
FrankenPHP 的 Caddy 版本必须内置 Mercure 插件,官方镜像一般满足,但自定义构建可能遗漏:
- 进容器执行
caddy list-modules | grep mercure,有输出才说明插件已注册 - 若无输出,说明当前 Caddy 二进制不支持 Mercure,需换用
dunglas/frankenphp官方镜像,不要自行编译或混用社区版 Caddy - 日志里搜
mercure关键字:docker logs frankenphp 2>&1 | grep mercure,启动时应有类似enabled mercure module的提示
最常被忽略的一点:Mercure 不是“配完就通”,它依赖 Caddy 插件链完整加载。哪怕只漏一个环境变量、或 Caddyfile 里多了一个空行导致语法解析中断,整个 mercure 块都会静默失效——此时 /.well-known/mercure 就是 404,且没有任何错误日志报出。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











