frankenphp生产部署核心是用frankenphp build生成含php运行时、caddy服务器及应用代码的单二进制文件,实现零依赖“拷过去就能跑”;需先清理非必要文件、生成生产自动加载器、设app_env=prod,再执行构建命令指定域名,最后赋权运行并确保端口开放以支持自动https。

FrankenPHP 生产部署的核心是用 frankenphp build 打出一个带完整运行时的单二进制文件,而不是在服务器上装 PHP、Caddy、Composer 一堆依赖——它不依赖系统环境,拷过去就能跑。
构建前必须清理和固化应用状态
二进制会把当前目录下所有能读到的文件(包括缓存、日志、.env)一起打包,不清理会导致体积膨胀、启动失败或泄露敏感信息:
- 删掉
.git、tests/、vendor/bin/、storage/logs、storage/framework/cache等非运行必需目录 - 执行
composer dump-autoload --optimize --no-dev,避免 dev-only 类被加载 - 确认
.env中APP_ENV=prod且APP_DEBUG=false;Laravel/Symfony 还要跑php artisan config:clear和php artisan view:clear - 检查
public/index.php能否本地响应 HTTP 200,FrankenPHP 默认只托管public/目录
用 frankenphp build 生成可执行文件
这一步产出的就是最终部署物,不是中间产物。它包含 PHP 运行时、Caddy 服务器、你的代码和配置,全部静态链接进一个文件:
- 确保已安装
frankenphpCLI(macOS 推荐brew install dunglas/tap/frankenphp;Linux/Windows 从 GitHub Releases 下载对应二进制并加入$PATH) - 在项目根目录运行:
frankenphp build --output myapp --server-name example.com -
--server-name是关键:它决定 Let's Encrypt 证书申请域名,生产环境必须填真实已解析的域名;测试可用localhost,但无法自动 HTTPS - 加
--no-compress可跳过 UPX 压缩(调试时建议加上,避免压缩导致符号丢失或反向工程困难) - 生成的
myapp文件通常 40–70MB,Linux/macOS 下直接chmod +x myapp即可执行
上线后权限、端口与 HTTPS 自动化
单文件虽小,但运行时行为和传统服务一样受系统约束,不能只 chmod 就完事:
- 目标服务器需开放 80 和 443 端口(UDP 443 用于 HTTP/3),否则 Let's Encrypt 会卡在 ACME HTTP-01 挑战
- 首次运行
./myapp会自动申请证书,耗时约 5–15 秒;若失败,看日志里是否出现acme: error或timeout,大概率是 DNS 未生效或防火墙拦截 - 强制 HTTP 模式调试用:
SERVER_NAME=:80 ./myapp,此时访问http://localhost即可,不走 TLS - 后台常驻不要用
nohup ./myapp &应对生产——推荐 systemd(Linux)或 launchd(macOS),保证崩溃自动重启、日志归集、资源限制
别忽略 worker 模式和 Mercure 的隐含依赖
如果你在代码里用了 frankenphp_worker_start() 或 mercure_publish(),这些功能不会因打包而失效,但它们的行为和部署方式强相关:
- worker 模式下,PHP 代码常驻内存,
__construct、static::boot()等初始化逻辑只执行一次——数据库连接、Redis 客户端、全局缓存都得自己做连接池或重连逻辑,否则长连接超时后会静默失败 - Mercure Hub 默认关闭,必须在 Caddyfile 或构建时通过 Go tag 启用;单二进制中若没启用,调用
mercure_publish()会直接返回 false,无报错提示 - 所有 PHP 扩展(如
ext-mbstring、ext-pdo_mysql)必须在构建时就存在,FrankenPHP 不支持运行时dl()或动态加载 .so —— 这点和传统 PHP-FPM 完全不同
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











