必须关掉opcache、worker模式、mercure/vulcain推送、访问日志和调试功能,并限制num_threads为2–3、upload_tmp_dir指向磁盘、docker内存设硬上限。

小内存服务器上必须关掉哪些默认功能
FrankenPHP 默认启用的很多特性在 1GB 以下机器上是“内存杀手”,不关掉会直接触发 OOM Killer 杀进程,连日志都来不及写。重点不是调小 memory_limit,而是砍掉非必要常驻模块:
-
opcache.enable=0:OPcache 占用独立内存(默认 128MB),小内存机建议彻底禁用;若必须开,至少设opcache.memory_consumption=32且opcache.max_accelerated_files=10000 -
frankenphp { num_threads 2 }:默认是 CPU 核数 × 2,4 核机器会起 8 个线程——每个线程常驻 20MB+,8 个就是 160MB+,直接砍到 2 或 3 个更安全 - 禁用
worker模式:worker 模式会让整个框架常驻内存,对 ThinkPHP/Laravel 这类项目,单实例就吃掉 50–80MB;小内存机老老实实用 classic 模式(即每次请求重新初始化) - 移除
mercure和vulcain相关配置:这两个实时推送模块各自额外占用 30–50MB 内存,且依赖额外服务端口,在小内存 VPS 上基本不可用
上传和临时文件必须手动限流
FrankenPHP 默认把上传文件先塞进内存,max_memory_upload 默认只有 ~2MB,但一旦上传稍大(比如 5MB 的图片),就会立刻 fallback 到磁盘 —— 而它默认用 /tmp,小内存机器往往 /tmp 是 tmpfs(内存文件系统),等于直接吃光剩余内存。
必须显式配置:
- 在 Caddyfile 的
frankenphp块里加:upload_tmp_dir /var/tmp(确保该路径挂载在真实磁盘上) - 同时设
upload_max_filesize 4M和post_max_size 6M(用php_ini指令),避免用户发大包触发内存抖动 - 检查宿主机
/var/tmp是否存在且可写;Docker 部署时需volumes: - /host/var/tmp:/var/tmp
Docker 内存限制要卡死在硬边界
很多人只改 php.ini 里的 memory_limit=64M,但 FrankenPHP 容器总内存由 cgroup 控制,不设 -m 就等于没限制。小内存服务器(如 512MB/1GB 实例)必须:
-
docker run -m 512m --memory-swap=512m:禁用 swap,防止 OOM 前疯狂换页拖垮整机 - Compose 中写死:
mem_limit: 512m+mem_reservation: 256m(预留基础内存,防冷启动瞬间 spike) - 别信
num_threads auto:auto 在 1C1G 机器上仍可能起 2 线程,但加上 OPcache、Caddy 自身、PHP 扩展后,256MB 常驻内存很容易突破 512MB 总限
精简日志和调试功能保命
开发期友好的日志级别在小内存机器上是负担。FrankenPHP 默认把 PHP 错误、Caddy 访问日志、慢日志全打开,每秒百次请求就能撑爆 128MB 的 /dev/shm(很多 Alpine 镜像默认用它存日志)。
- 关闭访问日志:
log { output discard }(Caddyfile 全局或站点块内) - PHP 错误只报致命级:
php_ini error_reporting 0+php_ini display_errors Off - 删掉所有
debug、profiling、xdebug相关扩展(镜像里默认不带,但有人会自己apk add) - 如果必须看错误,改用
error_log /proc/1/fd/1直接打到 stdout,由 Docker 捕获,不落地占磁盘
小内存不是不能跑 FrankenPHP,而是它默认太“胖”。真正关键的不是参数调多少,而是敢不敢关——关掉 OPcache、关掉 worker、关掉 Mercure、关掉日志,再把内存限制钉死,剩下的才是能活下来的配置。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











