docker实现php多版本共存的核心是各版本运行于独立容器,通过nginx反向代理、域名路由或端口隔离区分访问,共享mysql/redis等基础服务,挂载项目代码与配置,确保环境隔离、互不干扰。

直接用 Docker 实现 PHP 多版本共存,不是靠“在一个容器里装多个 PHP”,而是让每个版本跑在独立容器里,靠 Nginx 路由 + 自定义网络通信 + 域名隔离来区分访问。只要镜像标签写对、fastcgi_pass 指向正确服务名、/etc/hosts 配好,就能同时打开 old.test 和 new.test,各自走不同 PHP 版本,互不干扰。
docker-compose.yml 里怎么定义多个 PHP 版本服务
关键不是堆服务,而是确保每个 PHP 容器有唯一服务名、固定内部端口、明确镜像标签,并共享同一自定义网络。
-
php56和php72必须是不同服务名,不能都叫php;否则 Nginx 的fastcgi_pass php:9000会无法解析 - 镜像必须显式带标签:
php:5.6.40-fpm、php:7.2.34-fpm-alpine,别用latest—— 它可能指向 8.3,导致老项目直接报错 - 所有 PHP 服务和 Nginx 都要声明
networks: [backend],否则容器间ping php56会失败 - PHP 容器不需要
ports:暴露到宿主机(除非你真要直连),暴露反而增加端口冲突风险;Nginx 才需要ports: ["80:80"]
Nginx vhost 配置里 fastcgi_pass 怎么写才有效
fastcgi_pass 后面填的是 Docker 内网的服务名 + 端口,不是 127.0.0.1 或 localhost,也不是宿主机的 127.0.0.1:9000 —— 那样会连不上。
- 写成
fastcgi_pass php56:9000;:前提是docker-compose.yml中该服务名为php56,且它监听9000(FPM 默认端口) - 不能写
fastcgi_pass 127.0.0.1:9000;:这是指 Nginx 容器自己的回环地址,而 PHP 并不在这个容器里 - 如果 PHP 容器改了监听地址(比如只绑
127.0.0.1:9000),需在php-fpm.conf里改成listen = 9000或listen = 0.0.0.0:9000 - 配置改完必须 reload:用
docker exec nginx nginx -s reload,不是重启容器;否则新server_name不生效
为什么 hosts 加了域名却打不开,或者 502 Bad Gateway
502 几乎全是 fastcgi_pass 连不通导致的;打不开则大概率是 DNS 或路由没走到对应 server 块。
-
/etc/hosts只负责把old.test解析成127.0.0.1,不负责端口或后端转发 —— 这是 Nginx 的事 - 检查 Nginx 日志:
docker-compose logs -f nginx | grep "connect to",如果出现connect() failed (111: Connection refused),说明php56容器根本没起来,或没在backend网络里 - 进 Nginx 容器手动测试连通性:
docker exec -it nginx sh -c "apk add curl && curl -v http://php56:9000"—— 如果返回空或 connection refused,问题一定出在 PHP 容器本身 - 浏览器访问
http://old.test却跳到了 default server?检查server_name old.test;是否拼错,是否漏了分号,是否被其他server块的default_server拦截
PHP 扩展装不上或 composer install 报 missing extension
官方 PHP 镜像默认极简,mbstring、pdo_mysql、curl 这些都不是开箱即用的 —— 必须在构建时显式安装。
- 在 PHP 容器的 Dockerfile 或
docker-compose.yml的build步骤里加:RUN docker-php-ext-install mbstring pdo_mysql curl - 别用
apt-get install php-mbstring:Debian/Alpine 镜像里根本没有这个包,官方镜像是源码编译的,只能走docker-php-ext-*工具链 - 某些扩展依赖系统库:比如
gd要先RUN apt-get install -y libfreetype6-dev libjpeg62-turbo-dev libpng-dev,再docker-php-ext-install gd - 装完扩展必须启用:
docker-php-ext-enable mbstring(有些新版镜像自动启用,但老版本如 5.6 需手动)
最常被忽略的一点:PHP 容器启动后,php -m 看到的扩展列表,和 Nginx 实际调用时加载的不是一回事 —— 因为 FPM 有自己的 php.ini 加载路径。务必进容器执行 php-fpm -t && php-fpm -i | grep extension_dir,确认扩展文件真被加载进了 FPM SAPI 的运行时环境里。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











