frankenphp 是嵌入 php 运行时的定制版 caddy 二进制,非独立插件或搭配软件;它共用一个进程、一份 caddyfile 配置,启动即提供 http/https/静态文件与 php 执行能力。

FrankenPHP 就是 Caddy 的一个内置 PHP 应用插件
它不是“搭配使用”的两个独立软件,而是 FrankenPHP 二进制本身就是一个定制版 Caddy —— 编译时把 libphp 直接嵌进去了。启动 frankenphp php-server,你看到的其实是 Caddy 的 HTTP 服务、TLS 管理、静态文件逻辑,加上内建的 PHP 执行器,共用一个进程、一份配置(Caddyfile)。所以不存在“先装 Caddy 再装 FrankenPHP”,官方安装脚本下载的就是这个融合体。
安装后直接运行却报错 exec: "frankenphp": executable file not found
这是 PATH 没配好最常见的情况。官方一键安装脚本默认把二进制放到 /usr/local/bin/frankenphp,但某些 Linux 发行版(比如 Alpine 或最小化 CentOS)的 $PATH 不包含该路径。
- 先确认文件是否存在:
ls -l /usr/local/bin/frankenphp - 如果存在但命令不可用,临时加 PATH:
export PATH="/usr/local/bin:$PATH",再试frankenphp --version - 要永久生效,把上面那行写进
/etc/profile或用户家目录下的~/.bashrc - Docker 用户注意:
dunglas/frankenphp镜像里frankenphp已在 PATH 中,无需额外配置
用 Docker 启动后访问 404,或 PHP 文件被直接下载而不是执行
根本原因是 Caddyfile 里漏了 php_server 指令。FrankenPHP 不会自动识别 .php 文件 —— 它不像传统 Nginx 那样靠 location ~ \.php$ 匹配,而是靠显式启用 PHP 处理模块。
- 最简可用配置必须含这两块:
{ frankenphp { } } yourdomain.com { php_server } - 如果项目入口是
public/index.php(如 Laravel),还要加重写规则:php_server { rewrite * /index.php?{query} } - 别把
php_server放在reverse_proxy后面——它不转发,是直接执行;放错位置会导致请求被跳过 - 检查
Caddyfile是否在当前工作目录,FrankenPHP 默认只读当前目录下的该文件
num_threads 设太高反而变慢,怎么调才合理
FrankenPHP 的线程池不是越多越好。每个线程会常驻加载一次 PHP 解释器+OPcache+框架 bootstrap,内存占用随线程数线性增长;而真实并发请求数受 CPU 核心和 I/O 瓶颈限制。设成 auto 通常比硬编码更稳。
-
num_threads 2:适合本地开发或 1C1G 的轻量服务器 -
num_threads auto:推荐生产环境首选,它按runtime.NumCPU()自动设为 CPU 核心数 -
max_threads 8:可设略高于num_threads,用于突发流量,但别超过物理核心数 × 2 - 观察指标:用
ps aux | grep frankenphp看实际活跃线程数,再对比htop里 CPU/内存使用率 —— 如果 CPU 没跑满但内存吃紧,说明线程冗余了
FrankenPHP 的“简单”是建立在理解它和 Caddy 是一体两面的基础上的;最容易忽略的,是把它当成传统 LNMP 去套用 Nginx 思维,结果卡在 php_server 漏写、PATH 不对、或线程乱调上。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











