一个服务器装两个 php 完全可行,主流方案是 Docker 容器隔离或 PHP-FPM 多实例共存,配置得当互不干扰。这两种方式我都实际折腾过,下面把具体操作、坑点、选型逻辑一次说清。
为什么一台服务器要装两个 php
老项目跑在 PHP 5.6 或 7.4,新项目想用 PHP 8.2,这是最常见的场景,据 PHP 官方支持政策,PHP 7.4 安全支持在 2026 年 11 月已终止,PHP 8.0 在 2026 年 11 月终止,但很多存量业务代码就是升级不动,强行改代码成本太高。
再一个场景是同一台机器跑多个客户的站点,不同客户锁定的框架版本不一样,要是全用同一个 php,总有一方跑不起来,行业共识是版本隔离比强行统一更务实。
有人问能不能直接改系统默认 php 版本?能,但治标不治本,你改完命令行生效了,nginx 的 fastcgi 进程可能还连着旧的 php-fpm socket,到时候新旧请求混在一起,排查起来头疼,核心诉求是互不干扰地跑两套版本,而不是表面上切换个默认版本。
用 Docker 装两个 php 容器
这是我最推荐的方式,干净利落,不用碰宿主机环境。
我给一个 docker-compose.yml 的骨架,分别跑 php7.4 和 php8.2:
services:
php74:
image: php:7.4-fpm
container_name: php74
volumes:
- /var/www/site-a:/var/www/html
networks:
- web
command: php-fpm
php82:
image: php:8.2-fpm
container_name: php82
volumes:
- /var/www/site-b:/var/www/html
networks:
- web
command: php-fpm
nginx:
image: nginx:latest
container_name: nginx
ports:
- "80:80"
volumes:
- /var/www:/var/www
- ./nginx/conf.d:/etc/nginx/conf.d
networks:
- web
networks:
web:
driver: bridge
nginx 配置里分别把不同站点指到不同容器:
server {
listen 80;
server_name old-site.com;
root /var/www/site-a;
location ~ .php$ {
fastcgi_pass php74:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

include fastcgi_params;
}
}
server {
listen 80;
server_name new-site.com;
root /var/www/site-b;
location ~ .php$ {
fastcgi_pass php82:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
docker 方案最省心的点在于,每个容器内部的 php 扩展、依赖库完全独立,你不需要考虑系统是 centos 还是 ubuntu,更不需要纠结 apt 源里有没有你要的 php 版本,跑起来就两个字:隔离。
配 mysql 也简单,做个 mariadb 容器出来,两个 php 都能连,只要把容器加入同一个 docker network。
服务器怎么装两个 php 不用 Docker,原生共存
不想用 Docker 或者机器配置太老的,也可以原生装两个 php-fpm,思路很简单:分别编译安装两个版本,监听不同端口或 socket 文件,nginx 按站点转发。
先装依赖,这个各家系统大同小异,以 ubuntu 22.04 为例:
apt update
apt install -y build-essential libxml2-dev libssl-dev libcurl4-openssl-dev pkg-config libpng-dev libjpeg-dev libonig-dev libzip-dev
下载编译 php7.4:
curl -O https://www.php.net/distributions/php-7.4.33.tar.gz
tar xzf php-7.4.33.tar.gz
cd php-7.4.33
./configure --prefix=/usr/local/php74 --with-config-file-path=/usr/local/php74/etc --enable-fpm --with-mysqli --with-pdo-mysql --with-openssl --with-zlib --enable-mbstring
make -j$(nproc)
make install
编译 php8.2 同理,把 –prefix 改成 /usr/local/php82 即可。
然后配置两个 fpm 的监听端口:
php74 的 pool 配置文件 /usr/local/php74/etc/php-fpm.d/www.conf:
listen = 127.0.0.1:9074
php82 的 pool 配置文件 /usr/local/php82/etc/php-fpm.d/www.conf:
listen = 127.0.0.1:9082
端口别用 9000,很多老教程默认 9000,两个版本要是都配 9000,第二个起不来,端口只要机器上没被占用,随便挑。
启动各自的 fpm:
/usr/local/php74/sbin/php-fpm
/usr/local/php82/sbin/php-fpm
接着改 nginx,把 fastcgi_pass 指过去:
server {
listen 80;
server_name legacy.com;
root /var/www/legacy;
location ~ .php$ {
fastcgi_pass 127.0.0.1:9074;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
server {
listen 80;
server_name modern.com;
root /var/www/modern;
location ~ .php$ {
fastcgi_pass 127.0.0.1:9082;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
重载 nginx:
nginx -s reload
到这一步,一个服务器装两个 php 就落地了,旧站走 9074,新站走 9082,互不打扰。
原生共存方式的优点是不依赖 docker 那套 verbose 的镜像拉取过程,内存占用也小一些,缺点是编译耗时、后期扩展管理麻烦,装上 redis 扩展得分别给两套 php 各编译一遍。
Docker 和原生共存怎么选
| 对比维度 | Docker 双容器 | 原生 PHP-FPM 多实例 |
|---|---|---|
| 隔离性 | 强,进程和文件系统全隔离 | 中等,共用宿主机内核 |
| 部署速度 | 快,镜像拉下来就能起 | 慢,编译安装花时间 |
| 内存占用 | 相对较高 | 低,更适合小内存机器 |
| 扩展管理 | 各自容器内独立安装 | 两套 php 都要重复编译扩展 |
| 维护成本 | 低,重装即还原 | 高,依赖手动管理 |
| 适合场景 | 线上多项目隔离 | 一台机器跑两个老项目 |
内存低于 2G 的机器,我建议原生共存,跑 docker daemon 本身就要吃一部分内存,内存够大(4G 以上)就无脑 docker。
一台服务器安装多个 php 版本之后,日常怎么切
项目多了以后,命令行下经常要确认当前用哪个 php:
which php
php -v
原生共存方式下,系统默认 php 是你编译时最后加入 PATH 的那个,需要临时切换时:
export PATH=/usr/local/php74/bin:$PATH
php -v
想让站点目录自带版本识别,我习惯在项目根目录放一个 .env,标记“本目录运行 PHP 7.4,fastcgi 端口 9074”,方便运维同事日后查。
排查 502 时常用两条命令,一条看 php-fpm 进程是否存活:
ps aux | grep php-fpm
另一条直接请求 fpm 的 status 接口,在 pool 配置里打开 pm.status_path,curl 访问就有结果。
关于这个配置的常见疑问
一个服务器装两个 php 怎么保证端口不冲突
监听端口必须唯一,原方案里一个用 9074,一个用 9082,就不可能撞,如果用了 unix socket 文件,则确保 socket 文件路径不同,/tmp/php74-fpm.sock 和 /tmp/php82-fpm.sock,nginx 里 fastcgi_pass 的写法对应改成 unix:/tmp/php74-fpm.sock; 这种格式。
两个 php 共存会不会拖慢网站速度
不会,php-fpm 是按 worker 进程数吃资源的,多一套 php 就多几个常驻进程,内存增加幅度大概每个 worker 20-40MB,站点并发低时几乎没有感知,真正拖慢速度的是业务代码自身有没有性能瓶颈,而不是多跑了一个 php 版本,需要留意的是别把两个 php-fpm 的 worker 数都调得极大,比如都设成 max_children=50,那内存占用就会比较可观,合理控制 worker 数量,即便 2G 内存的机器也能跑两个 php 实例加一个小型数据库。
怎么验证当前站点跑的是哪个 php 版本
在站点根目录放一个 phpinfo 文件最直接:
echo "<?php phpinfo(); ?>" > /var/www/legacy/info.php
浏览器访问 http://your-domain/info.php,页面顶部显示 PHP Version 那一行就是当前站点实际使用的版本,确认完立刻删掉这个文件,生产环境留着 phpinfo 等于给攻击者送信息。
验证完别忘了一件事,分别访问旧项目和新项目的 phpinfo 页面,确认它们确实走到了不同端口对应的 php-fpm,这一步做完,整个方案才算闭环。
首发原创文章,作者:王坚,如若转载,请注明出处:https://idctop.com/article/681108.html





