FrankenPHP是集成Caddy与PHP运行时的单二进制现代应用服务器,无需Nginx、PHP-FPM或手动证书管理;只需frankenphp二进制、正确Caddyfile和index.php即可快速启动服务。

FrankenPHP 不是“另一个 PHP 安装方式”,它是把 Caddy + PHP 运行时打包进一个二进制的现代应用服务器。今天就能上线的前提很明确:你不需要配 Nginx、不用管 PHP-FPM 进程池、不手动申请证书——只要 frankenphp 二进制可执行,Caddyfile 写对,index.php 存在,服务就起来了。
确认系统支持和基础依赖
FrankenPHP 是 Go 编译的静态二进制,不依赖系统 PHP 环境,但对运行平台有硬性要求:
- Linux/macOS 可直接运行;Windows 必须用 WSL2,原生 Windows 不支持(Go 交叉编译未提供 Windows 版)
- 需要
cap_sys_ptrace权限(尤其 Docker 场景下),否则 worker 模式会启动失败 - 若要用 Let’s Encrypt 自动签发 HTTPS,必须有公网域名解析到该机器(裸 IP 不被 ACME 支持)
- PHP 代码本身仍需满足版本要求:Laravel Octane 场景下需
PHP ≥ 8.1;纯 FrankenPHP HTTP 服务最低支持 PHP 7.4,但强烈建议 8.1+
快速验证本地是否能跑通
跳过所有构建步骤,用最简路径验证环境是否 ready:
- 下载对应平台的
frankenphp二进制(官网或dunglas/frankenphpDocker 镜像里提取) - 新建测试目录,放入
index.php:<?php echo "OK: " . $_SERVER['SERVER_SOFTWARE'] ?? 'unknown';
- 在同一目录写
Caddyfile::8080 { php_server } - 执行
./frankenphp run(不是frankenphp start,后者用于 daemon 模式) - 访问
http://localhost:8080—— 若返回 OK 且含frankenphp字样,说明底层链路已通
注意:php_server 指令默认走 classic 模式(类似 FPM 的 per-request 生命周期),如需常驻加速,得显式启用 worker 模式并提供入口脚本。
立即学习“PHP免费学习笔记(深入)”;
Docker 中跑生产级服务的关键配置点
用官方镜像 dunglas/frankenphp 启动容器看似简单,但几个配置项漏掉就会卡在 502 或空白页:
-
SERVER_NAME环境变量必须设置,例如SERVER_NAME=example.com;若只跑本地开发,设为SERVER_NAME=:80(冒号开头表示监听所有地址的 80 端口) - 静态文件路径要和 Caddyfile 对齐:默认 Caddy 期望
/app/public是文档根,所以COPY . /app/public要么全量复制项目,要么只复制 public 目录内容 - HTTPS 自动生效的前提是
/data卷持久化:Caddy 把证书存在/data下,没挂载就每次重启都重申请,可能触发 Let’s Encrypt 速率限制 - OPcache 必须显式启用:镜像中
opcache.enable=1默认关闭,需在php.ini或通过RUN docker-php-ext-enable opcache打开
Worker 模式启动失败的典型表现和修复
很多人在 Laravel Octane 场景下执行 php artisan octane:start --server=frankenphp 后报错 command not found: frankenphp-worker.php,本质是 worker 入口缺失:
- 必须先运行
php artisan octane:install --server=frankenphp,它会生成vendor/bin/frankenphp-worker.php并下载frankenphp二进制到vendor/bin/ - 检查该文件是否存在且可执行:
ls -l vendor/bin/frankenphp*;若权限不对,执行chmod +x vendor/bin/frankenphp-worker.php - worker 模式下不能直接用
frankenphp run启动,必须由 Octane 控制进程生命周期;否则会提示 “no worker script provided” - 常见静默失败场景:CI/CD 构建阶段跳过
octane:install(因无交互终端),应显式加--force参数并确保vendor/bin在 PATH 中
真正容易被忽略的是:FrankenPHP 的 worker 模式和 classic 模式共享同一份 Caddyfile,但请求路由逻辑不同——worker 会接管全部 PHP 请求,而 classic 仍走 fastcgi-like 分发。混用时若没关掉旧的 Nginx 配置或残留 proxy_pass,就会出现 502 错误却查不到日志。



















