PHP容器化核心是理清服务生命周期与网络通信逻辑:php-fpm-alpine默认仅监听127.0.0.1:9000或socket,Nginx需通过服务名(如php:9000)而非localhost连接;扩展安装须先装Alpine依赖再docker-php-ext-install并重启进程;WebSocket必须用cli镜像+CMD启动+TCP健康检查,不可用Apache。

PHP容器编程不是学“怎么写PHP”,而是学“怎么让PHP在容器里活下来、跑得稳、扩得快”。直接上Dockerfile却不懂FPM生命周期,或硬套Nginx配置却忽略端口暴露逻辑,90%的失败都发生在这类认知断层里。
php:8.2-fpm-alpine镜像为什么总报502?
根本原因不是代码错,是服务没对上。php:8.2-fpm-alpine只启动php-fpm进程,不带Web服务器,也不监听80端口——它默认只监听127.0.0.1:9000(TCP)或/var/run/php/php8.2-fpm.sock(Unix socket)。Nginx若配置成fastcgi_pass localhost:9000,在Docker网络中会失败,因为localhost指向容器自身,而fpm根本没在那开监听。
- 必须显式配置fpm监听外部可访问地址:
listen = 0.0.0.0:9000(TCP)或listen = /var/run/php/php8.2-fpm.sock+listen.owner = nginx+listen.group = nginx(socket) - Docker Compose中Nginx与PHP容器必须同network,且Nginx的
fastcgi_pass要写成php:9000(服务名),不是localhost - Alpine下记得装
apk add nginx或用单独nginx容器,别指望fpm镜像里有nginx
docker-php-ext-install安装扩展后php -m不显示?
常见于GD、cURL、mbstring等扩展,本质是编译路径或依赖缺失。官方PHP镜像用源码编译方式管理扩展,和apt/apt-get冲突,也和Alpine的musl libc行为不一致。
- 不要用
apt-get install php-gd——这装的是Debian包,路径、so文件名、依赖链全错 - 正确流程:先
apk add --no-cache $DEPENDENCIES(如g++ jpeg-dev zlib-dev libpng-dev),再docker-php-ext-configure gd --with-jpeg-dir=/usr/include/ --with-png-dir=/usr/include/,最后docker-php-ext-install gd - 装完必须重启PHP进程:
kill -USR2 1(fpm主进程PID=1)或docker restart容器,php -m才刷新 - 检查扩展是否真加载:
php --ini确认conf.d/路径被扫描,ls /usr/local/etc/php/conf.d/看有没有docker-php-ext-gd.ini
WebSocket服务为什么不能用php:8.2-apache?
Apache + mod_php是请求-响应模型,每个HTTP请求启动一个PHP进程,结束后立即销毁。WebSocket需要长连接、事件循环、内存常驻——这和Apache的生命周期天然互斥。
立即学习“PHP免费学习笔记(深入)”;
- 必须换CLI镜像:
FROM php:8.2-cli-alpine,不是fpm或apache - Swoole/Workerman启动脚本要用
CMD ["php", "server.php"],不能靠Apache转发;否则连接建立即断 - Dockerfile里要暴露WS端口(如
EXPOSE 9501),并在docker-compose.yml中映射到宿主机,ports: ["9501:9501"] - 健康检查不能用HTTP探针(
curl http://localhost:9501会超时),得用TCP探针:tcpSocket: port: 9501
真正卡住人的,从来不是语法或命令,而是“哪个进程该监听什么、谁连谁、谁负责重启、谁管超时”。容器里没有systemctl,没有cron守护,所有生命周期都得自己用CMD、healthcheck、restart_policy、信号处理来补全——漏掉任意一环,服务就静默死亡。



















