必须加 -p 443:443/udp,因为 FrankenPHP 内置 Caddy 默认启用 HTTP/3(基于 QUIC 协议),而 QUIC 强制依赖 UDP 443 端口通信;缺此映射则 UDP 包被 Docker 网络层丢弃,HTTP/3 静默失效。

为什么 docker run 要加 -p 443:443/udp
FrankenPHP 内置 Caddy,默认启用 HTTP/3(基于 QUIC 协议),而 QUIC 必须走 UDP 端口 —— 443/udp 不是可选项,是 HTTP/3 的传输层硬要求。
常见错误现象:
• 浏览器 DevTools 显示“h2”或“http/1.1”,但没出现“h3”
• curl -I --http3 https://localhost 报错“HTTP/3 not supported”
• Chrome 地址栏右上角不显示闪电图标(QUIC 指示)
-
-p 443:443/tcp只负责 HTTPS(TLS + HTTP/1.1 或 HTTP/2) -
-p 443:443/udp才让 QUIC 数据包能进容器,Caddy 才能响应 HTTP/3 请求 - 缺了 UDP 映射,FrankenPHP 进程本身仍会监听 UDP 443,但 Docker 网络层直接丢弃所有入向 UDP 包
- 不需要额外配置 Caddyfile 或环境变量:只要端口映射到位,Caddy 自动启用 HTTP/3
host 网络模式下还要不要映射 443/udp?
不用。使用 --network host 时,容器直接共享宿主机网络栈,UDP 443 就是宿主机的 UDP 443 —— 但你得确保:
• 宿主机防火墙(如 firewalld 或 ufw)放行 UDP 443
• 云厂商安全组(阿里云/腾讯云)显式允许 443/udp(很多控制台默认只开 TCP)
容易踩的坑:
• 混用 --network host 和 -p 443:443/udp:Docker 会忽略后者并警告,但用户误以为“已配好”
• 只开了 TCP 443 安全组,没开 UDP 443 → HTTP/3 在公网完全不可用,本地测试却正常(因本地绕过防火墙)
立即学习“PHP免费学习笔记(深入)”;
监听地址和 SERVER_NAME 会影响 HTTP/3 吗?
不影响。HTTP/3 启用与否只取决于两个条件:
• Caddy 是否监听 :443(TCP+UDP)
• 宿主机或容器网络是否允许 UDP 443 流量通过
SERVER_NAME 仅控制 TLS 证书行为和 HTTP 跳转逻辑:
• SERVER_NAME=:80 → 关闭 HTTPS,HTTP/3 自动禁用(因无 TLS)
• SERVER_NAME=example.com → 启用 HTTPS + HTTP/3(前提是端口和防火墙就位)
• SERVER_NAME=localhost → Caddy 用本地自签名证书,HTTP/3 仍可用(curl --http3 https://localhost 可验证)
真正卡住 HTTP/3 的,从来不是配置项,而是 UDP 端口在某一层被拦住了 —— 从 docker ps 看不到 UDP 映射、ss -tuln | grep :443 看不到 udp 行、云控制台没勾选 UDP 协议,这三个地方漏一个,HTTP/3 就静默失效。



















