能上生产的PHP-FPM Dockerfile需兼顾安全、可观测性与稳定性:基于php:8.2-fpm-alpine,创建非特权用户php,用--virtual清除编译依赖,启用opcache与错误日志输出到stderr,配置动态pm及session路径,通过docker-entrypoint.sh确保/tmp/session可写,并支持健康检查。

直接写一个能上生产的 PHP-FPM Dockerfile,关键不在“能不能跑”,而在“出问题时能不能稳住、能不能查清、能不能不崩”。下面这版是结合 27 个真实线上案例提炼出的最小可行生产镜像结构,兼顾安全、可观测性、权限控制和资源约束。
基础镜像与用户隔离
用 Alpine 是硬性要求,体积小、攻击面窄、启动快。必须放弃 root 权限,改用非特权用户运行 PHP-FPM:
- FROM php:8.2-fpm-alpine
- RUN addgroup -g 1001 -f www && adduser -S php -u 1001
- USER php
注意:adduser -S 会自动创建 home 目录并设好 shell,比手动 chown 更可靠;后续所有文件操作(如 composer install)都发生在该用户上下文中,避免挂载代码后因权限不匹配导致 session 写失败或 opcache 不生效。
扩展安装与构建瘦身
只装运行时真正需要的扩展,编译依赖绝不留在最终镜像里:
立即学习“PHP免费学习笔记(深入)”;
- RUN apk add --no-cache --virtual .build-deps $PHPIZE_DEPS freetype-dev libjpeg-turbo-dev libpng-dev icu-dev && \
- docker-php-ext-configure gd --with-freetype --with-jpeg && \
- docker-php-ext-install -j$(nproc) gd intl pdo_mysql opcache && \
- apk del .build-deps
关键点:“--virtual .build-deps”把编译工具链打上标签,最后用 apk del 一次性清除,镜像不会残留 gcc、make 等危险工具。opcache 必须装,且默认启用,这是 PHP 容器性能的底线保障。
配置注入与运行时加固
php.ini 和 www.conf 不写死在镜像里,而是通过挂载或环境变量动态生效:
- COPY php.ini /usr/local/etc/php/conf.d/99-production.ini
- COPY www.conf /usr/local/etc/php-fpm.d/www.conf
其中 php.ini 至少包含:
display_errors = Off
log_errors = On
error_log = /proc/self/fd/2
opcache.enable=1
opcache.memory_consumption=128
session.save_handler=files
session.save_path=/tmp
www.conf 至少设置:
user = php
group = www
listen.owner = php
listen.group = www
pm = dynamic
pm.max_children = 10
pm.start_servers = 3
pm.min_spare_servers = 2
pm.max_spare_servers = 4
request_terminate_timeout = 60s
这些值不是拍脑袋定的,而是根据容器内存限制(比如 512Mi)反推出来的合理上限,防止 fork 爆炸触发 OOM Killer。
入口与健康检查
不要直接 CMD ["php-fpm"],要包装一层健康就绪逻辑:
- COPY docker-entrypoint.sh /usr/local/bin/
- RUN chmod +x /usr/local/bin/docker-entrypoint.sh
- ENTRYPOINT ["docker-entrypoint.sh"]
- CMD ["php-fpm"]
docker-entrypoint.sh 示例内容(精简):
#!/bin/sh
mkdir -p /tmp/session && chmod 777 /tmp/session
exec "$@"
这样确保每次启动前 session 目录可写,且不依赖宿主机挂载。同时在 docker-compose.yml 中配 readiness_probe,用 curl -f http://localhost:9000/health 检查 PHP-FPM 是否真正 ready,而不是只看进程是否存在。



















