PHP Docker化需关注php.ini配置、opcache启用、扩展加载顺序及Nginx-PHP-FPM通信;推荐开发用debian基php:8.2-apache,生产若需精简可选alpine但须处理SSL和扩展编译;Nginx须通过服务名fastcgi_pass php:9000并统一UID或设socket权限。

PHP 应用 Docker 化不是“打包就能跑”,关键在于 php.ini、opcache 配置、扩展加载顺序和 Web 服务器耦合方式——这些不调好,容器一启动就 502 Bad Gateway 或 Class not found。
怎么选基础镜像:alpine 还是 debian?
别直接抄别人 FROM php:8.2-apache 就完事。alpine 镜像小(~50MB),但 gd、imagick 等扩展编译麻烦,glibc 兼容性差;debian 镜像大(~400MB),但扩展安装稳定,apt install 直接可用,CI/CD 构建快。
实操建议:
- 开发/测试环境优先用
php:8.2-apache(debian base),省去扩展编译步骤 - 生产环境若追求极致体积且无复杂扩展依赖,用
php:8.2-cli-alpine+ 自建nginx容器,但必须手动apk add --no-cache $PHPIZE_DEPS再docker-php-ext-install - 避免混用
php:alpine和mysql:8.0的 SSL 连接,alpine 默认不带libssl1.1,会报mysqli_connect(): SSL connection error
Dockerfile 里怎么正确装扩展?
用 docker-php-ext-install 装扩展时,漏掉依赖或顺序错,会导致 extension=xxx.so 加载失败但容器不报错,PHP-FPM 启动后直接拒绝请求。
常见踩坑点:
-
pdo_mysql必须在pdo之后安装:docker-php-ext-install pdo pdo_mysql,不能颠倒 -
opcache要显式启用:docker-php-ext-enable opcache,否则即使编译进 PHP 也不生效 - 装
redis前得先pecl install redis,再docker-php-ext-enable redis;直接docker-php-ext-install redis会失败(它只支持内置扩展) - 修改
php.ini别用COPY php.ini /usr/local/etc/php/全量覆盖——会丢掉镜像自带的date.timezone、upload_max_filesize等默认值,改用RUN echo "opcache.enable=1" >> /usr/local/etc/php/conf.d/opcache.ini
怎么让 nginx 和 php-fpm 正确通信?
用 php:8.2-fpm 镜像时,nginx 容器无法通过 localhost:9000 访问 PHP-FPM,因为 Docker 容器间 localhost 不互通,必须用服务名。
典型 compose 结构:
services:
web:
image: nginx:alpine
volumes:
- ./src:/var/www/html
- ./nginx.conf:/etc/nginx/nginx.conf
depends_on:
- php
php:
image: php:8.2-fpm
volumes:
- ./src:/var/www/html
对应 nginx.conf 中的 fastcgi_pass 必须写成:
fastcgi_pass php:9000;
而不是 127.0.0.1:9000 或 localhost:9000。另外,php-fpm.conf 默认监听 127.0.0.1:9000,需改成 0.0.0.0:9000 或 unix socket(推荐):
RUN sed -i 's/listen = 127.0.0.1:9000/listen = \/var\/run\/php\/php-fpm.sock/' /usr/local/etc/php-fpm.d/www.conf RUN sed -i 's/;listen.owner/listen.owner/' /usr/local/etc/php-fpm.d/www.conf
最常被忽略的是权限:nginx 容器用户(www-data)和 php-fpm 容器用户 UID 不一致时,socket 文件无法读写,connect() failed (111: Connection refused) while connecting to upstream 就是这个原因。要么统一设为 user: "82:82",要么把 socket 改成 listen.mode = 0666。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











