frankenphp部署symfony需显式配置caddyfile路由分流、绝对路径php_worker指令、public/worker.php入口、env app_env=prod及max_requests 5000,发布时必须frankenphp stop-workers而非reload,否则静态404、api失效、更新不生效。

FrankenPHP 部署 Symfony 项目不是简单复制代码加启动命令就能跑通的事。核心难点不在 Symfony 本身,而在 FrankenPHP 的运行模型:它把 Caddy、PHP 运行时和 worker 生命周期深度耦合,必须显式配置路由分流、worker 入口、环境变量和发布流程,否则静态资源 404、API 不响应、更新后逻辑不生效是常态。
必须显式配置 Caddyfile 路由分流
FrankenPHP 默认以 public/ 为根目录,且 php_server 是全局 fallback。前后端分离项目(如 Vue + Symfony API)若不干预,Caddy 会把所有请求——包括 /dist/app.js 或 /index.html——都当作 PHP 脚本执行,导致 500 或空白响应。
-
前端静态资源优先匹配:用
handle+try_files明确指定 dist 目录路径,例如root * /app/dist,再配try_files {path} {path}/ /index.html支持 SPA history 模式 -
API 路径单独转发:对
/api/*、/login、/logout等路径,必须写独立handle块并内嵌php_server,不能依赖兜底规则 -
避免全局 php_server:删掉或注释掉站点块末尾的无条件
php_server,否则所有未命中静态路径的请求(比如/admin)都会进 Symfony,可能触发意外路由拦截
启用 worker 模式要配对且路径绝对
worker 模式不是“开了就行”,而是 Caddyfile 指令、入口文件、环境变量三者严格联动的结果。错一个环节,日志静默、PID 每次变、性能无提升。
-
入口必须是
public/worker.php:Symfony ≥6.3 官方提供该文件,专为常驻设计;用index.php会导致 autoloader 重置、Class not found 等问题 -
php_worker路径必须绝对:例如/var/www/myapp/public/worker.php,不能是./public/worker.php或public/worker.php—— Caddy 启动时工作目录不可控 -
必须传环境变量:在
php_worker块里加env APP_ENV=prod,否则容器加载走 dev 模式,缓存失效 -
务必设
max_requests:推荐max_requests 5000,防止单 worker 内存泄漏卡死;FrankenPHP 会在达到后自动 fork 新实例,旧实例处理完当前请求再退出
发布新版本必须 stop-workers,不能 reload
Caddy reload 只刷新路由规则,不会让已运行的 worker 加载新代码。改完 PHP 文件直接 reload,用户看到的仍是旧逻辑。
-
正确流程分两步:先部署新代码(确保
var/cache可写、composer install --no-dev --optimize-autoloader执行完成),再执行frankenphp stop-workers -
stop-workers是优雅滚动:它不中断正在处理的请求,只通知活跃 worker 处理完当前请求后退出;新请求由新 worker(加载了新代码)接管 -
不要用
kill或systemctl restart:这会强制终止全部连接,造成用户请求中断
安全头与 Mercure 需额外适配
FrankenPHP 的 Caddy 层默认注入安全响应头(如 X-Content-Type-Options),会覆盖 Symfony 的 security_headers 配置;Mercure 也不是插件,而是编译进二进制的 Go Hub,需显式启用。
-
禁用 Caddy 默认安全头:在站点块中,
php或php_worker指令前加security_headers off,把控制权交还给 Symfony -
Mercure 必须在 Caddyfile 中声明
mercure块:设置publish_origins和cors_origins,开发时加insecure;删掉docker-compose.yml里的独立 Mercure service,否则端口冲突 -
前端订阅要用合法 JWT:PHP 后端签发,payload 中
mercure.subscribe必须是非空绝对 URI 数组,算法仅支持 HS256
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











