构建阶段必须使用dunglas/frankenphp:static-builder镜像,而非运行时镜像;需执行composer install --no-dev --optimize-autoloader、设置embed=public/、绑定git哈希命名产物、注入生产环境变量并校验二进制可执行性。

构建阶段必须用静态构建镜像,不能直接 run dunglas/frankenphp
FrankenPHP 的 static-builder 镜像是专为打包设计的,它内置了 Go 构建链、PHP 源码和 Caddy 编译环境。如果在 CI 中直接基于 dunglas/frankenphp 运行时镜像去“复制代码 + 启动”,得到的只是可运行容器,不是独立二进制文件——这违背了 FrankenPHP 打包的核心价值。
常见错误现象:./build-static.sh 报错找不到 go 或 phpize,或生成的二进制启动时报 undefined symbol: php_json_decode_ex;根本原因是用了运行时镜像而非构建镜像。
- 始终以
FROM dunglas/frankenphp:static-builder作为基础镜像 - 确保
COPY . .包含完整项目(尤其是public/和composer.json) - 构建前必须执行
composer install --no-dev --optimize-autoloader,否则 vendor 内容不会被嵌入二进制 -
EMBED=环境变量必须指向应用根目录(如EMBED=public/),路径错误会导致入口文件找不到
标签必须绑定 Git 提交哈希,避免 latest 覆盖风险
FrankenPHP 产物是单二进制文件,不可分层复用,每次构建都应产出唯一、可追溯的文件名。用 latest 当文件名或对象存储 key,会导致回滚失败、版本混淆。
使用场景:你修复了一个路由解析 bug,提交哈希是 def5678,期望发布后能快速定位该二进制对应哪次代码变更。
- 在 GitHub Actions 中,用
${{ github.sha }}获取短哈希(前 7 位),拼成myapp-def5678 - 若需区分分支,组合为
myapp-main-${{ github.sha }} - 上传到对象存储(如 OSS/S3)时,key 必须包含该标签,例如
releases/myapp-main-def5678 - 禁止在 workflow 中写
mv myapp myapp-latest—— 这会破坏可追溯性
发布动作要校验二进制可执行性,不能只看构建成功
构建脚本退出码为 0 不代表产物真的能跑。FrankenPHP 二进制依赖系统级库(如 libsqlite3)、正确嵌入的 PHP 扩展、以及入口路径存在性。CI 流水线里漏掉验证,上线后才发现 502 就晚了。
容易踩的坑:本地测试通过,但 CI runner 是干净 Ubuntu 环境,缺少 libc6-dev 或 zlib1g-dev,导致 build-static.sh 静默跳过某些扩展编译。
- 构建完成后立即执行:
./myapp --version && timeout 5s ./myapp --help | head -n 1 - 检查是否吐出 FrankenPHP 版本号且不 panic
- 用
ldd ./myapp | grep "not found"确认无缺失动态库(即使静态链接也建议扫一遍) - 若项目含 SQLite,加一步
timeout 3s ./myapp 'SELECT 1' 2>/dev/null || exit 1验证 PHP 扩展加载
部署到服务器前必须替换环境变量,不能硬编码 .env
FrankenPHP 二进制在构建时会读取当前目录下的 .env 并内联进可执行文件。如果 CI 构建用的是开发环境变量(如 APP_DEBUG=1),产物直接上生产,就等于把调试模式暴露在公网。
关键点:环境变量注入必须发生在构建阶段,且与部署目标解耦。不能靠 SSH 登录后改配置文件,那会绕过 CI 的一致性保障。
- CI 中准备两套
.env:一个用于构建(APP_ENV=prod APP_DEBUG=0),一个留作部署模板(含占位符如DB_HOST=__DB_HOST__) - 构建命令前插入:
echo "APP_ENV=prod\nAPP_DEBUG=0" > .env - 禁止在
build-static.sh后再修改.env—— 此时变量已固化进二进制 - 若需运行时动态配置(如数据库地址),用 FrankenPHP 的
--env-file参数配合部署脚本注入,而非塞进二进制
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











