frankenphp容器内存限制不能只设memory_limit,因其采用多线程模型,memory_limit仅限单请求,而容器总内存由docker/cgroup硬限制,需按线程数×单请求内存(含opcache等)估算并显式配置-m或mem_limit,否则oom killer会直接杀进程。

FrankenPHP容器内存限制不能只设 memory_limit
很多人以为只要在 php.ini 里调大 memory_limit 就够了,其实这是个常见误解。FrankenPHP 是多线程模型(不是传统 PHP-FPM 的多进程),整个容器共享同一块内存空间,memory_limit 只控制单个 PHP 请求的内存上限,而容器总内存由 Docker 或宿主机 cgroup 控制——两者不互通,超限时会被 OOM Killer 直接杀掉进程,连错误日志都不留。
容器级内存限制要按线程数 × 平均请求内存估算
FrankenPHP 默认启用线程池(num_threads auto),每个线程可并发处理一个请求;每个请求实际占用的内存远不止 memory_limit 声明值——OPcache、加载的扩展、框架 autoload、静态资源缓存等都会额外吃内存。实测 Laravel + OPcache 启用后,单请求常驻内存约 25–40MB(不含峰值)。
- 8 核服务器上
num_threads 8→ 建议容器内存下限设为512MB,保守起见推荐1GB - 16 核或高负载场景(如含 Mercure/Vulcain 实时推送)→ 至少
2GB,否则容易触发 OOM - 纯 API 服务(无模板渲染、轻量框架)→ 可压到
384MB,但需配合opcache.memory_consumption=128防止 OPcache 挤占过多
docker run 和 compose.yaml 中必须显式限制
不加限制等于裸奔。FrankenPHP 容器若没设内存上限,在资源争抢时会把宿主机拖垮,尤其和数据库、Redis 共部署时风险极高。
正确做法是显式声明:docker run -m 1g ... dunglas/frankenphp
或在 compose.yaml 中写:
services:
php:
image: dunglas/frankenphp
mem_limit: 1g
mem_reservation: 512m
mem_reservation 能让 Docker 预留基础内存,避免冷启动抖动;mem_limit 是硬上限,超了就 kill。
OPcache 配置不当会让内存问题雪上加霜
FrankenPHP 默认启用 OPcache,但它的内存是独立于 PHP memory_limit 的。如果 opcache.memory_consumption 设太高(比如 512M),又没配 opcache.max_accelerated_files 匹配项目文件数,会导致 OPcache 频繁失效、重编译,反而推高内存波动。
- 中型 Laravel 项目(~5k PHP 文件):用
opcache.memory_consumption=128+opcache.max_accelerated_files=100000 - 务必检查
opcache_get_status()返回的opcache.hit_rate和oom_restarts字段,后者非零说明 OPcache 已被挤爆过 - 不要盲目开
opcache.preload—— 预加载文件过大(如全框架类)会直接吃掉数百 MB 内存,且无法被单个请求释放
memory_limit 错觉,掩盖了容器整体内存的真实压力。上线前务必用 docker stats 观察稳定期 RSS 峰值,而不是只看 PHP 日志里的 “Allowed memory size exhausted”。php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











