编程 FrankenPHP 装法与运行:Go 写的 PHP 应用服务器,php-server 与 Worker 怎么配

2026-09-18 20:01:16

FrankenPHP 装法与运行:Go 写的 PHP 应用服务器,php-server 与 Worker 怎么配

项目地址:github.com/dunglas/frankenphp,官网:frankenphp.dev

它是什么

FrankenPHP 是一个用 Go 编写的 PHP 应用服务器,直接构建在 Caddy 之上。PHP 解释器通过 CGO 以原生方式嵌入 Go 运行时,省掉了 PHP-FPM 与 Web 服务器之间的进程间通信。它可以服务任意 PHP 应用,也能作为独立的 Go 库使用:只要应用基于 net/http,就可以把 PHP 嵌进去。

核心特性:

  • Early Hints(103 状态码):PHP 响应完整生成前提前推送关键资源。
  • Worker 模式:常驻内存的 PHP Worker。
  • 实时能力:内置 Mercure.rocks。
  • 热重载:文件变更后自动重载 PHP 线程。
  • 自动 HTTPS 与 HTTP/2、HTTP/3:继承 Caddy 的证书管理与协议支持。

安装

一键脚本(Linux / macOS):

curl https://frankenphp.dev/install.sh | sh

Windows PowerShell:

irm https://frankenphp.dev/install.ps1 | iex

独立二进制:官方为 Linux、macOS、Windows 提供免安装二进制,内置 PHP 8.5;Linux 版为静态链接,不依赖系统库。

rpm(dnf):

sudo dnf install https://rpm.henderkes.com/static-php-1-0.noarch.rpm
sudo dnf module enable php-zts:static-8.5   # 8.2–8.5 可用
sudo dnf install frankenphp

扩展用 sudo dnf install php-zts-;默认未提供的走 PIE:

sudo dnf install pie-zts && sudo pie-zts install asgrim/example-pie-extension

deb(apt):

VERSION=85   # 82–85 可用
sudo curl https://pkg.henderkes.com/api/packages/${VERSION}/debian/repository.key -o /etc/apt/keyrings/static-php${VERSION}.asc
echo "deb [signed-by=/etc/apt/keyrings/static-php${VERSION}.asc] https://pkg.henderkes.com/api/packages/${VERSION}/debian php-zts main" | sudo tee -a /etc/apt/sources.list.d/static-php${VERSION}.list
sudo apt update && sudo apt install frankenphp

apk(Alpine):

VERSION=85
echo "https://pkg.henderkes.com/api/packages/${VERSION}/alpine/main/php-zts" | sudo tee -a /etc/apk/repositories
KEYFILE=$(curl -sJOw '%{filename_effective}' https://pkg.henderkes.com/api/packages/${VERSION}/alpine/key)
sudo mv ${KEYFILE} /etc/apk/keys/ && sudo apk update && sudo apk add frankenphp

Homebrew:

brew install dunglas/frankenphp/frankenphp

扩展统一通过 PIE 安装。仓库 package/ 目录提供 debian / rhel / alpine 三种打包平台的服务文件,deb、rpm 包内置 systemd 服务单元。

两条核心命令

frankenphp php-server 启动生产级 PHP 服务器。服务当前目录的 PHP 应用直接跑:

frankenphp php-server

它本质是动态构造 Caddy 配置并启动 HTTP 服务。没有 --domain 时默认监听 :80,请求按「目录重定向 → 重写到 index.php → PHP 执行 → 静态文件服务」处理。

常用参数:

  • --domain / -d:指定域名启用 HTTPS,自动切 443 并签发证书,需要先配好 A/AAAA 记录。
  • --root / -r:网站根目录。
  • --listen / -l:自定义监听地址,默认 :80,指定域名时为 443。
  • --worker / -w:启用 Worker 模式,可逗号指定 Worker 数量。
  • --watch:监听文件变更触发热重载。
  • --access-log / -a:启用访问日志。
  • --debug / -v:详细调试日志。
  • --mercure / -m:启用内置 Mercure Hub。
  • --no-compress:关闭压缩。

默认不加 --no-compress 时会自动启用 zstd、br、gzip,按 zstd → br → gzip 的优先级协商。

frankenphp php-cli 以 CLI SAPI 方式执行 PHP 脚本:

frankenphp php-cli /path/to/your/script.php

它保持 PHP CLI SAPI 的参数语义,其余参数原样透传,返回脚本退出码。可以把 frankenphp php-cli 当作 php 命令的替代品,用来跑 Composer、Artisan 等工具。

deb / rpm 包安装后可用 systemd 启动:

sudo systemctl start frankenphp

Docker 部署

docker run -v .:/app/public \
-p 80:80 -p 443:443 -p 443:443/udp \
dunglas/frankenphp

随后访问 https://localhost。不要用 https://127.0.0.1,用 https://localhost 并接受自签名证书。换域名用 SERVER_NAME 环境变量。443/udp 用于 HTTP/3(QUIC)。容器内默认使用 caddy/frankenphp/Caddyfile 作为配置模板。

配置体系

FrankenPHP、Caddy 以及内置的 Mercure、Vulcain 模块都使用 Caddy 支持的配置格式,最常用的是 Caddyfile。默认在当前目录查找 Caddyfile,也可用 -c / --config 指定。

最小可用 Caddyfile:

localhost {
encode zstd br gzip
php_server
}

php_server 等价于 php 指令加静态文件服务。

全局 frankenphp 配置块(Caddy 全局选项):

{
frankenphp {
num_threads    # PHP 线程数,默认 CPU 数 × 2
max_threads    # 运行时额外启动上限,默认 num_threads,可设 auto
max_wait_time     # 请求等待空闲线程的最大超时
max_idle_time     # 自动扩容线程空闲多久后停用,默认 5s
max_requests           # 实验性:线程处理多少请求后重启,缓解内存泄漏,默认 0
php_ini         # 设置 php.ini 指令
worker {
file
# Worker 脚本路径
num                  # 启动线程数,默认 CPU 数 × 2
env
watch
# 监听文件变更路径
name
max_consecutive_failures    # 连续失败多少次判定不健康,默认 6
}
}
}

php.ini 的位置按安装方式区分:

  • Docker:主配置 /usr/local/etc/php/php.ini(默认不提供,需要自己复制模板),附加目录 /usr/local/etc/php/conf.d/*.ini
  • RPM / Debian 包:主配置 /etc/php-zts/php.ini(默认提供生产预设),附加目录 /etc/php-zts/conf.d/*.ini
  • 静态二进制:先在执行目录查找 php.ini,其次 /etc/frankenphp/php.ini,附加目录 /etc/frankenphp/php.d/*.ini。静态二进制无法加载外部扩展,扩展必须编译进二进制。

自定义镜像里复制模板:

FROM dunglas/frankenphp
RUN cp $PHP_INI_DIR/php.ini-production $PHP_INI_DIR/php.ini

默认 Caddyfile 模板通过 {$SERVER_NAME:localhost} 支持域名覆盖,{$SERVER_ROOT:public/} 设置站点根目录,默认启用 encode zstd br gzip,预留 Mercure / Vulcain 入口,并通过 import Caddyfile.d/*.caddyfile 加载额外片段。

Worker 模式原理

一个 worker 结构体描述一份 Worker 脚本,可以绑定多个 PHP 线程,每个 Worker 维护独立请求通道、线程池与连续失败计数器。启动时按 Worker 预分配线程,默认是 CPU 核数的 2 倍;请求直接在常驻线程内处理,避免传统 PHP-FPM 每个请求重新初始化整个运行时的开销。热重载由 --watch 触发,文件变更后自动重启相关 Worker 线程。

生态集成

框架集成方面,FrankenPHP 与任何 PHP 应用兼容,为 Laravel、Symfony 提供官方 Worker 模式集成,WordPress 也有集成文档。它可以作为独立 Go 库,把 PHP 嵌入任何基于 net/http 的 Go 应用;也支持创建自执行的独立 PHP 应用。生产部署、性能调优、日志与可观测性另有文档。

复制全文 生成海报 PHP FrankenPHP Caddy Docker Go

推荐文章

程序员茄子在线接单