FrankenPHP默认启用OPcache但常未生效,因php.ini中opcache.enable=1被注释;需取消注释、确认zend_extension=opcache.so路径正确、重启容器,并用opcache_get_status()验证非空数组返回。

FrankenPHP 默认已启用 OPcache,但必须验证是否真在工作
不用手动“开启”,因为 dunglas/frankenphp 镜像默认启用了 OPcache,并预加载了 opcache.so;但很多用户部署后发现性能没提升、代码更新不生效,问题出在「默认启用 ≠ 当前生效」。
常见错误现象:
- 访问
phpinfo()页面,看到 “Opcode Caching” 显示 Disabled -
opcache_get_status()返回false或空数组 - 改了 PHP 文件,刷新页面仍是旧逻辑(不是浏览器缓存,也不是 CDN 缓存)
根本原因:FrankenPHP 使用的是 php.ini-production,该文件里 opcache.enable=1 是注释掉的(`;opcache.enable=1`),而镜像启动时并不会自动取消注释。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 进入容器执行
php --ini,确认加载的配置路径(通常是/usr/local/etc/php/php.ini) - 编辑该
php.ini,找到;opcache.enable=1行,删掉开头分号,改为opcache.enable=1 - 检查是否漏掉
zend_extension=opcache.so—— FrankenPHP 镜像中该行通常已存在且未注释,但务必确认它在[opcache]段落之前、且路径正确(Linux 下就是opcache.so,无需写全路径) - **重启容器**:
docker restart your-frankenphp-container—— 仅 reload 不生效,FrankenPHP 是单进程模型,必须重启
为什么 opcache.validate_timestamps=1 在 FrankenPHP 里更关键
FrankenPHP 基于 Caddy + PHP 的嵌入式运行模式,没有传统 FPM worker 进程池;每个请求由同一个长期运行的 PHP 进程处理,OPcache 缓存复用率极高 —— 这既是优势,也放大了时间戳校验失效的风险。
如果你用 rsync 或挂载 volume 方式热更新代码(比如 docker run -v ./src:/app/public),NFS 或 overlayfs 可能导致文件 mtime 不更新或延迟,此时若设 opcache.validate_timestamps=0,就会永远卡在旧 opcode 上。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 开发/CI/CD 场景:保持
opcache.validate_timestamps=1+opcache.revalidate_freq=2(每 2 秒检查一次),平衡可见性与性能 - 生产镜像部署(COPY 构建):可设
opcache.validate_timestamps=0,但必须在每次发布后调用opcache_reset()(FrankenPHP 支持该函数,CLI 下执行docker exec -it container php -r 'opcache_reset();'即可) - 千万别在
php.ini里写opcache.revalidate_freq=0—— 它只在validate_timestamps=1下才有效,设成 0 实际等同于每请求检查,开销反而更大
opcache.memory_consumption 要按实际项目调,别信默认值
FrankenPHP 默认沿用 PHP 官方 php.ini-production,其中 opcache.memory_consumption=64。对 Laravel、Symfony 或含 Composer autoload 的项目,64MB 很快就爆满,表现为 opcache_get_status()['opcache_statistics']['oom_restarts'] > 0 —— 这意味着缓存被强制清空重来,性能比不开还差。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 进容器跑命令估算文件数:
find /app/public -name "*.php" | wc -l,结果乘以 1.5,填到opcache.max_accelerated_files(比如 8000 → 设 12000) -
opcache.memory_consumption至少设128(中小项目),大项目直接256;FrankenPHP 内存占用本身不高,多给点无副作用 - 上线后观察
opcache_get_status()中的hits / (hits + misses),长期低于 0.95 就要查是不是内存不够或文件数超限
最常被忽略的一点:FrankenPHP 的日志默认不输出 OPcache 启动失败信息,zend_extension 路径错、so 文件权限不对、或与其他扩展冲突时,它会静默跳过加载 —— 所以别只看 phpinfo(),一定要用 opcache_get_status() 验证返回值是否为非空数组。



















