要使用docker部署多个php站点并实现项目隔离,核心在于利用容器的隔离特性,为每个项目提供独立的运行环境,并通过反向代理进行流量分发;1. 每个项目使用独立的docker-compose.yml文件定义所需服务,如php-fpm、nginx、数据库等,并配置专属网络实现服务隔离;2. 每个项目的nginx服务监听宿主机的不同端口(如8080、8081);3. 宿主机运行主nginx反向代理,根据域名将80/443端口的请求转发至对应项目的nginx容器端口;4. 通过宿主机或docker内部的反向代理实现统一入口和动态路由;5. 各项目代码、配置、容器网络独立,确保php版本、扩展、依赖互不干扰;6. 优化方面包括文件i/o性能调整、php-fpm参数优化、数据库持久化、日志调试与端口冲突处理,最终实现高效、灵活、可扩展的多php站点部署架构。

使用Docker部署多个PHP站点,核心在于利用容器的隔离特性,为每个项目提供独立的运行环境。这通常通过为每个项目创建独立的docker-compose.yml文件来实现,配合一个统一的反向代理(如Nginx)进行流量分发,从而确保不同PHP应用之间互不干扰,各自拥有所需的PHP版本、扩展和依赖。

部署多个PHP站点并实现项目隔离,最有效的方式是为每个PHP应用构建一套独立的Docker容器栈,并利用Docker的网络功能和宿主机的反向代理来管理流量。
具体来说,每个PHP项目(例如:project-a和project-b)都会有自己的docker-compose.yml文件,定义了该项目所需的PHP-FPM、Nginx(或Caddy)、数据库(如MySQL/PostgreSQL)等服务。这些服务在各自的Docker网络中运行,互不干扰。
立即学习“PHP免费学习笔记(深入)”;

例如,project-a的docker-compose.yml可能包含一个PHP-FPM服务和一个Nginx服务,它们通过内部网络连接。project-b也类似。
# project-a/docker-compose.yml 示例
version: '3.8'
services:
app:
build:
context: .
dockerfile: Dockerfile.php
volumes:
- ./src:/var/www/html
networks:
- project_a_net
web:
image: nginx:latest
volumes:
- ./src:/var/www/html
- ./nginx.conf:/etc/nginx/conf.d/default.conf
ports:
- "8080:80" # 注意这里的端口,后续会通过宿主机Nginx代理
depends_on:
- app
networks:
- project_a_net
networks:
project_a_net:
driver: bridge# project-a/nginx.conf 示例
server {
listen 80;
server_name project-a.local; # 宿主机hosts文件配置
root /var/www/html;
index index.php index.html index.htm;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass app:9000; # app是php-fpm服务名
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
}每个项目启动后,其Nginx服务会监听一个独立的端口(例如project-a监听宿主机8080,project-b监听宿主机8081)。

最后,在宿主机上运行一个主Nginx反向代理,它监听标准的80/443端口,并根据请求的域名将流量转发到对应项目的Docker Nginx容器的内部端口。
# 宿主机Nginx配置 /etc/nginx/sites-available/default
server {
listen 80;
server_name project-a.local;
location / {
proxy_pass http://localhost:8080; # 转发到project-a的Nginx容器
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
server {
listen 80;
server_name project-b.local;
location / {
proxy_pass http://localhost:8081; # 转发到project-b的Nginx容器
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}这样,当访问project-a.local时,宿主机Nginx会把请求转发给project-a的Docker Nginx容器,再由其转发给project-a的PHP-FPM容器处理。project-b.local同理。
说实话,在Docker普及之前,管理多个PHP项目简直是噩梦。不同的项目可能需要PHP 5.6、PHP 7.4、PHP 8.1,或者不同的MySQL版本、Redis扩展等等。那种依赖冲突,版本升级的阵痛,现在想起来都头疼。
选择Docker进行PHP多站点部署,最直接的理由就是彻底的隔离性。每个项目都在自己的容器里运行,拥有独立的PHP版本、扩展和依赖环境,相互之间完全不干扰。这意味着你可以同时运行一个老旧的PHP 5.6项目和一个最新的PHP 8.2项目,它们都能和谐共存。这在传统LAMP/LNMP环境中几乎是不可想象的。
其次是环境一致性。开发、测试、生产环境可以基于相同的Docker镜像和docker-compose配置,大大减少了“在我机器上能跑”的问题。部署新项目或者将现有项目迁移到新服务器,只需要git clone,然后docker-compose up -d,简直不要太方便。这种确定性对团队协作和CI/CD流程至关重要。
还有就是资源管理。相比于为每个项目都开一台虚拟机,Docker容器轻量得多,启动速度快,对系统资源的占用也更少。虽然每个项目都有自己的Nginx和PHP-FPM容器,但它们共享宿主机的操作系统内核,效率高得多。而且,如果你需要某个项目进行扩容,直接调整其docker-compose文件中的服务副本数就行,操作起来非常灵活。对我而言,它解决了长久以来PHP开发环境配置的痛点,让我可以更专注于代码本身。
实际操作起来,PHP容器多项目隔离部署主要围绕docker-compose和反向代理展开。
1. 项目目录结构规划:
这是基础,通常每个项目都会有一个独立的根目录,里面包含源代码和该项目专属的docker-compose.yml文件。
/var/www/
├── project-a/
│ ├── src/ # PHP 源代码
│ ├── docker-compose.yml # project-a 的服务定义
│ └── nginx.conf # project-a 的 Nginx 配置
├── project-b/
│ ├── src/ # PHP 源代码
│ ├── docker-compose.yml # project-b 的服务定义
│ └── nginx.conf # project-b 的 Nginx 配置
└── docker-proxy/ # 可选,如果使用Docker内的反向代理
└── docker-compose.yml # 统一的反向代理服务(如Nginx或Traefik)2. 编写各项目的docker-compose.yml:
每个项目的docker-compose.yml定义了其PHP-FPM服务、Web服务器(Nginx或Apache),以及可能的数据库、Redis等服务。关键点在于:
Dockerfile安装所需的扩展。volumes挂载项目代码和自定义的Nginx配置。bridge网络,确保服务间隔离。例如,project-a的服务在project_a_net中通信,project-b的服务在project_b_net中通信。project-a的Nginx映射到宿主机8080,project-b映射到8081。这是为了避免端口冲突,并为后续的统一反向代理做准备。3. 选择反向代理方案: 这是将外部请求路由到正确项目容器的关键。
方案一:宿主机Nginx作为反向代理(推荐简单场景)
这是最直接且易于理解的方式。在宿主机上安装并运行一个Nginx实例,监听80/443端口。其配置(如前面“解决方案”部分所示)根据请求的Host头(域名)将流量转发到对应项目Nginx容器在宿主机上映射的端口。
优点:简单,性能好,易于调试。
缺点:宿主机Nginx需要手动配置,每增加一个项目就要修改一次配置。
方案二:Docker内部的反向代理(如Nginx或Traefik)
这种方案更“Docker化”。创建一个单独的docker-compose.yml文件,运行一个专门的反向代理容器(例如,一个Nginx容器或者更高级的Traefik)。这个代理容器会连接到所有项目的Docker网络,并通过服务发现或标签(label)自动路由流量。
例如,使用Traefik,你只需要在每个项目的docker-compose.yml中为Nginx服务添加Traefik标签,Traefik就能自动发现并配置路由。
优点:自动化配置,动态更新,管理多个项目更方便。
缺点:初期配置可能略复杂,需要理解Traefik或Nginx代理容器的内部机制。
无论哪种方案,都需要确保宿主机的/etc/hosts文件(或DNS服务器)将project-a.local、project-b.local等域名解析到宿主机的IP地址(通常是127.0.0.1)。
Docker环境的部署并非一劳永逸,尤其是在开发和生产环境中,你可能会遇到一些性能、调试或配置上的小麻烦。
1. 性能瓶颈:文件I/O 在macOS或Windows上使用Docker Desktop时,宿主机与容器之间的文件同步(特别是通过bind mount挂载代码卷)可能会成为一个显著的性能瓶颈。PHP应用通常涉及大量小文件读写,这在虚拟化层面上效率不高。
docker-compose.yml的volumes配置中添加cached或delegated选项,例如:- ./src:/var/www/html:cached。这可以改善某些场景下的性能。docker-sync或mutagen这类工具,它们通过更高效的文件同步机制来解决这个问题。2. PHP-FPM配置优化: 确保PHP-FPM的配置适合你的应用负载。默认配置可能过于保守。
php.ini中opcache.enable=1,并调整opcache.memory_consumption、opcache.max_accelerated_files等参数。pm.max_children、pm.start_servers、pm.min_spare_servers、pm.max_spare_servers等参数。pm = dynamic通常是比较均衡的选择。3. 数据库持久化: 数据库容器的数据必须持久化,否则容器重启后数据会丢失。
docker-compose.yml中定义一个卷,并将其挂载到数据库容器的数据目录。services:
db:
image: mysql:8.0
volumes:
- db_data:/var/lib/mysql # 将数据持久化到db_data卷
volumes:
db_data:4. 调试与日志: 当应用出现问题时,日志是排查的关键。
docker logs <container_name>是你的好朋友。docker exec -it <container_name> bash或sh可以让你进入容器的命令行环境,进行文件查看、运行命令等操作。docker logs就能捕获到。5. 端口冲突与网络问题: 当你运行多个项目时,如果它们的Nginx容器都尝试映射到宿主机的同一个端口(例如80),就会发生冲突。
部署多站点确实会带来一些额外的配置复杂度,但一旦搭建起来,其带来的开发效率提升和环境管理上的便利性,绝对值得你投入精力去学习和实践。有时候,你可能需要在docker-compose文件里反复尝试端口映射,或者盯着Nginx日志找半天为什么请求没转发对,但这些都是过程,最终你会得到一个强大且灵活的开发与部署体系。
以上就是如何用Docker部署多个PHP站点 PHP容器多项目隔离部署策略的详细内容,更多请关注php中文网其它相关文章!
PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号