frankenphp 不是 caddy 插件,而是内嵌 php 运行时的定制版 caddy 二进制;php_server 指令仅在 frankenphp 二进制中有效,需用 frankenphp run 启动且确保 modules/php.so 存在并可读。

frankenphp 命令存在但 php_server 指令不识别
这是最典型的“看似装好了,实际没生效”现象。根本原因不是 Caddy 没加载模块,而是你运行的是系统自带的 caddy,不是 FrankenPHP 自带的定制版 frankenphp 二进制。
FrankenPHP 不是 Caddy 的插件,它本身就是一个重编译、内嵌 PHP 运行时的 Caddy 变体。所有 PHP 相关指令(如 php_server、frankenphp 全局块)只在 frankenphp 二进制里注册,原生 caddy 完全不认识。
- 检查当前用的是哪个二进制:
which caddy和which frankenphp—— 两者路径必须不同,且frankenphp --version输出应含frankenphp字样 - 不要用
caddy run启动带php_server的 Caddyfile;必须用frankenphp run - 如果你通过包管理器(如 apt、brew)装了 caddy,它会覆盖 PATH,导致敲
caddy就跑错进程;建议卸载或用完整路径调用/usr/local/bin/frankenphp run
Caddyfile 中 php_server 报 unknown directive 错误
错误信息类似:adapt: parsing caddyfile tokens for 'http.handlers.php_server': unknown directive 'php_server'。这说明 FrankenPHP 二进制虽在运行,但它的 PHP 模块未被正确启用——常见于非标准安装路径或权限问题。
FrankenPHP 在启动时会尝试加载 php.so(Linux/macOS)或 php.dll(Windows,但实际不支持),这个模块由安装脚本自动放置在二进制同级目录的 modules/ 子目录下。如果目录结构被破坏,模块就加载失败。
- 确认
frankenphp二进制所在目录下存在modules/php.so(Linux/macOS)或modules/php.dll(不推荐 Windows) - 检查文件权限:
ls -l $(dirname $(which frankenphp))/modules/,确保php.so可读 - 某些 CI/CD 或 Docker 构建中,安装脚本可能跳过模块下载;可手动补全:
curl -L https://github.com/dunglas/frankenphp/releases/download/v1.0.0-alpha.6/modules-php-linux-amd64.tar.gz | tar -xz -C $(dirname $(which frankenphp))(版本号按需替换)
使用 docker run dunglas/frankenphp 但静态文件 404 或 PHP 不执行
官方镜像默认以 frankenphp php-server 方式启动,它不读取本地 Caddyfile,而是走内置最小配置。这意味着你写的 php_server 指令完全不会生效,所有路由都由默认规则接管。
要让自定义 Caddyfile 生效,必须显式传入配置路径,并指定运行模式:
- 把你的
Caddyfile放进项目根目录,然后运行:docker run -v $(pwd):/app -p 80:80 dunglas/frankenphp frankenphp run --config /app/Caddyfile - 镜像中
frankenphp二进制位于/usr/bin/frankenphp,不是/usr/bin/caddy;别在 Dockerfile 里写ENTRYPOINT ["caddy", "run"] - 环境变量
SERVER_NAME仅影响镜像内置的简易模式,对自定义 Caddyfile 无效;域名和 TLS 配置必须写进 Caddyfile 本身
frankenphp run 启动后访问返回 500 且日志无 PHP 错误
现象是 HTTP 层有响应(比如返回了 HTML 框架),但 PHP 脚本没执行,或 index.php 被当成静态文件直接输出源码。这通常是因为路由匹配失败,请求根本没进 PHP 处理链。
FrankenPHP 的 php_server 是一个“匹配后处理”指令,它不会自动接管所有 .php 文件——你得明确告诉它哪些路径需要 PHP 执行:
- 最简有效写法:
php_server必须放在具体站点块(如example.com { ... })内部,不能只写在全局{ ... }块里 - 若用子路径部署(如
/myapp/),需加handle_path /myapp/*并配合php_server,否则路由前缀会被截断导致$_SERVER['SCRIPT_NAME']错乱 - 检查是否误用了
php(旧版指令,已弃用)而不是php_server;后者才是 FrankenPHP v1+ 的正式指令名
frankenphp --version 输出带版本号和 “frankenphp” 字样,再用 frankenphp run --config Caddyfile --adapter caddyfile 显式指定适配器,避免任何隐式 fallback。php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











