使用dunglas/frankenphp镜像需正确挂载路径(/app或/app/public)、同时映射443 tcp/udp端口、设置server_name环境变量匹配域名,并通过frankenphp_config启用worker模式。

直接用 dunglas/frankenphp 镜像就能跑起来,不需要额外装 PHP、Caddy 或配 TLS,连证书都是自动生成的——但必须注意挂载路径和端口映射规则,否则 404 或 HTTPS 报错是常态。
docker run 命令里 -v 挂载路径必须是 /app 或 /app/public
FrankenPHP 官方镜像默认把 Web 根目录设为 /app/public(Laravel/Symfony 等框架适用),或直接设为 /app(纯 PHP 脚本项目)。挂错路径会导致 Caddy 找不到 index.php,返回 404:
- 运行 Laravel:用
-v $PWD:/app,因为镜像内Caddyfile的root指向public/,而$PWD是项目根目录 - 运行单文件 PHP:用
-v $PWD:/app/public,让index.php直接落在public/下 - 不要写成
-v $PWD:/var/www/html—— 镜像不认这个路径,Caddy 会静默忽略
HTTPS 和 HTTP/3 必须同时暴露 443 TCP + 443 UDP 端口
只映射 -p 443:443 是不够的。HTTP/3 依赖 QUIC 协议,走的是 UDP,漏掉 UDP 映射会导致:
- 浏览器地址栏显示“安全连接已建立”,但实际降级到 HTTP/2
-
curl -I --http3 https://localhost报错HTTP/3 not supported - Caddy 日志里出现
failed to listen on UDP
正确写法是:
docker run -p 80:80 -p 443:443 -p 443:443/udp -v $PWD:/app dunglas/frankenphp
访问时用 https://localhost,浏览器会提示证书不受信——这是 Caddy 自签本地证书的正常行为,点“高级”→“继续访问”即可。
SERVER_NAME 环境变量决定 Caddy 虚拟主机匹配逻辑
默认情况下,镜像里的 Caddyfile 写的是 localhost,所以只响应 https://localhost。想用自定义域名(比如 myapp.test)必须传 SERVER_NAME:
- 本地开发:加
-e SERVER_NAME=myapp.test,再在 hosts 文件加127.0.0.1 myapp.test - 不设该变量时,
curl http://127.0.0.1会 404,因为 Caddy 不匹配 IP 地址,只匹配 Host 头 - 如果同时跑多个 FrankenPHP 容器,每个都得设不同
SERVER_NAME,否则 Caddy 会冲突或覆盖
worker 模式下必须通过 FRANKENPHP_CONFIG 注入启动脚本
想启用常驻内存的 worker 模式(比如跑 WebSocket 或后台任务),不能靠改 Caddyfile,得用环境变量注入:
- 命令行加
-e FRANKENPHP_CONFIG="worker ./public/chat.php" -
chat.php必须放在挂载路径下,且路径是容器内视角(如挂载$PWD:/app,就写./public/chat.php,不是./chat.php) - worker 启动后,日志里会出现
started worker "chat.php",没这行说明配置未生效 - 不要试图在
Caddyfile里写worker块——镜像内置的 Caddyfile 不解析该指令,只认FRANKENPHP_CONFIG
最易被忽略的一点:worker 模式下,PHP 脚本不会自动重载。改了代码必须重启容器,除非显式加 watch ./public/chat.php 到 FRANKENPHP_CONFIG 字符串里。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











