最稳妥选dunglas/frankenphp Docker镜像,本地二进制次之,独立打包二进制仅适用于离线交付等极简分发场景。

dunglas/frankenphp Docker 镜像最稳妥,本地二进制次之,独立打包二进制仅适合极简分发场景。
用 dunglas/frankenphp 镜像部署生产环境最省心
官方镜像已预装 PHP 8.5、Caddy、Opcache、PDO、cURL 等常用扩展,并默认启用 php.ini-production,无需手动调优。它把证书管理、HTTP/2/3、自动 HTTPS 全部封装好了,你只管挂载代码和配域名。
关键实操点:
-
SERVER_NAME必须设为真实域名(如example.com),不能是localhost或 IP;否则 Let's Encrypt 申请失败 - 必须挂载
caddy_data:/data卷,否则证书无法持久化,重启后反复申请导致触发 ACME 速率限制 - 不要 COPY 整个项目到
/app,Laravel/Symfony 应该只 COPYpublic/和.env,敏感文件(.env.example、storage/logs)别暴露 - 如果用
docker-compose,记得加restart: unless-stopped,避免容器异常退出后服务中断
本地二进制适合有运维控制权且想省资源的场景
Linux 静态链接版 frankenphp 二进制(如 frankenphp_1.2.0_linux_amd64.tar.gz)不依赖系统 PHP,启动快、内存占用低,适合跑在轻量云服务器或边缘设备上。
但要注意:
立即学习“PHP免费学习笔记(深入)”;
- Caddyfile 中必须显式写
root public/,漏掉会导致 404(Docker 镜像里这行是默认内置的) - 没有
php.ini文件路径提示,所有 PHP 配置得靠环境变量:比如PHP_INI_SCAN_DIR=/etc/php/conf.d,否则opcache.enable=1这类设置不生效 - UDP 端口(HTTP/3)需手动开放防火墙:
ufw allow 443/udp,Docker 自动处理了,本地运行得自己来 - 升级要手动下载新二进制、替换、重启进程,没镜像层缓存那么顺滑
独立打包二进制只在离线或交付场景有价值
把整个 Laravel 项目 + frankenphp 打包成单个可执行文件(./myapp),适用于给客户私有部署、内网系统、或嵌入硬件设备。但它牺牲了灵活性:
- 每次改 PHP 代码或配置,都得重新构建整个二进制,CI/CD 流程变重
- 无法动态加载扩展(如
redis.so),所有依赖必须静态编译进 Go 侧,兼容性风险高 - 日志默认输出到 stdout,没
systemd或supervisord管着,进程挂了就真没了 -
Caddyfile必须硬编码进二进制或通过--config指定外部路径,没法像 Docker 那样用环境变量注入
num_threads 和 php_server 配置容易被忽略
很多人以为 FrankenPHP 启动就完事了,其实两个参数直接影响并发能力:
-
num_threads控制 PHP worker 数量,默认是auto,但在 2 核以下小内存机器上会设成 1,建议显式写成2或4(不超过 CPU 核数 × 2) -
php_server块里漏掉try_files {path} index.php,会导致 Laravel 的路由全 404;Docker 镜像默认带了,但本地 Caddyfile 得手写 - 没开
encode zstd br gzip,静态资源不会压缩,首屏加载慢一倍以上
journalctl -u caddy。



















