php-fpm 默认监听 9000 端口是因官方配置约定(如 www.conf 中 listen = 127.0.0.1:9000),属 iana 用户端口范围,语义清晰且冲突低;但 docker 环境需改为 0.0.0.0:9000 或 uds 并配权限,否则 nginx 无法连接。

php-fpm 默认不监听 9000 端口,得手动改 www.conf
PHP 8.3 官方 php:8.3-fpm-alpine 或 php:8.3-fpm 镜像里,www.conf 默认把 listen 设成了 127.0.0.1:9000,但容器内没有传统意义上的“localhost 回环”,且 Docker 网络模型下,其他容器(比如 Nginx)根本连不上这个地址。更糟的是,某些 Alpine 版本甚至默认注释掉了 listen 行,导致 PHP-FPM 启动后根本不监听任何端口。
必须显式配置为监听 0.0.0.0:9000 或 Unix socket,并确保权限和用户匹配:
- 用
COPY覆盖默认/usr/local/etc/php-fpm.d/www.conf,或在 Dockerfile 中RUN sed -i 's/listen =.*/listen = 0.0.0.0:9000/' /usr/local/etc/php-fpm.d/www.conf - 确认
listen.allowed_clients没被设成127.0.0.1(它会拒绝来自其他容器的连接) - 如果用 Unix socket,
listen = /var/run/php/php-fpm.sock后要加listen.owner = www-data和listen.group = www-data,且 Nginx 容器需挂载同一路径
Alpine 下扩展安装失败常因缺少 pkgconf 和头文件
PHP 8.3 的 docker-php-ext-install 在 Alpine 上比以前更严格,pkgconf(替代 pkg-config)是硬依赖,不装就报 configure: error: Package requirements (libpng >= 1.6) were not met 这类错,哪怕你已经装了 libpng-dev。
典型修复步骤:
-
RUN apk add --no-cache pkgconf $PHPIZE_DEPS—— 必须先装pkgconf,再装其他-dev包 -
gd扩展要配--with-freetype --with-jpeg,但 Alpine 8.3 的freetype-dev已移至freetype-dev(不是freetype2-dev),名字别写错 -
opcache默认已内置,但启用需在php.ini加zend_extension=opcache,否则phpinfo()里看不到
容器启动后 php-fpm 进程退出,八成是用户权限或工作目录问题
PHP 8.3 镜像默认以 www-data 用户运行,但如果你挂载了宿主机代码目录,而该目录属主是 root 或 UID 1001,www-data(UID 82)很可能没读取权限,导致 php-fpm 启动时加载 index.php 失败,直接退出,日志只显示 ERROR: failed to post process the configuration 或干脆静默死亡。
解决方向很实际:
- 启动容器时加
--user 82:82强制用户,或提前在宿主机chown -R 82:82 /path/to/code - Dockerfile 里用
RUN chown -R www-data:www-data /var/www/html(注意路径要和WORKDIR一致) - 别用
COPY . /var/www/html后立刻chown,Alpine 的chown不支持-R对符号链接递归,会报错;改用find /var/www/html -exec chown www-data:www-data {} +
docker-compose.yml 里 fastcgi_pass 写 php:9000 前,先确认服务名和网络
很多人照抄教程写 fastcgi_pass php:9000,结果 Nginx 报 connect() failed (111: Connection refused) while connecting to upstream。这不是 PHP-FPM 没起来,而是 Nginx 根本解析不了 php 这个域名 —— 因为 docker-compose.yml 里 PHP 服务名不是 php,或者两个服务没在同一个自定义网络里。
检查三件事:
-
docker-compose.yml中 PHP 服务的service名字(如app、php-fpm)必须和 Nginx 配置里的fastcgi_pass值完全一致 - 两个服务都得显式声明
networks,不能只靠默认 bridge;推荐定义一个backend网络并共用 - 别信
links,Docker 23+ 已弃用,它不会自动注入 DNS 记录
复杂点在于:PHP 8.3 的 FPM 日志默认关着,error_log 和 access.log 都没开,出问题只能看 docker logs -f <container></container> 输出的 stderr。一旦挂载了自定义 www.conf,又忘了开 catch_workers_output = yes,子进程崩溃就只剩黑盒。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











