跳转到主内容
新派编程网 - 新潮编程理念,全新技术课堂!

如何在宝塔面板实现PHP项目的灰度发布?通过Nginx子目录分流不同版本

宝塔面板不支持子目录灰度部署,因默认PHP配置强制所有请求经主站index.php处理;需手动在Nginx配置中为子目录(如/v2/)添加独立location块,指定alias、try_files及关键fastcgi_param SCRIPT_FILENAME $request_filename,否则仍运行主站代码。 为什么直接用 Nginx 子目录做灰度在宝塔里容易失败 因为宝塔默认的 PHP 项目站点配置会强制将所有请求通过
index.php
入口统一处理,而子目录(比如
/v2/
)若没单独配置
root
和
fastcgi_param SCRIPT_FILENAME
,PHP 实际运行的仍是主站代码,根本不会加载新版本文件。 常见错误现象:
/v2/api/user
返回的是主站
v1
的响应,或直接 500(找不到
/v2/index.php
对应的物理路径)。 关键点在于:子目录不是简单加个 location 就行,它需要独立的 PHP 上下文环境。 在宝塔中为子目录配置独立 PHP 运行环境 必须手动修改站点配置,不能只靠宝塔界面“子目录绑定”功能(该功能仅适用于静态或完全隔离的二级站点,不适用同项目多版本灰度)。 立即学习 “ PHP免费学习笔记(深入) ”; 进入宝塔 → 网站 → 对应站点 → 配置文件 在
server
块内添加如下
location
块(以
/v2/
为例):
location ^~ /v2/ { alias /www/wwwroot/your-site.com/v2/; index index.php; try_files $uri $uri/ /v2/index.php?$query_string;
location ~ \.php$ {
    fastcgi_pass unix:/tmp/php-cgi-80.sock;
    fastcgi_index index.php;
    include fastcgi.conf;
    fastcgi_param SCRIPT_FILENAME $request_filename;  # 注意这里!不是 $document_root$fastcgi_script_name
}
} PHP 8.5.5 PHP 8.5.5 是 PHP 8.5 分支的维护更新版本。该版本延续了“小步快跑”的迭代逻辑,通过深度错误修复、底层性能微调以及安全加固,旨在为开发者提供一个更健壮、更高效的运行环境。该版本严格遵守语义化版本规范,不包含破坏性变更。 下载 重点说明:
alias
后路径末尾必须带
/
,否则
$request_filename
拼接出错
SCRIPT_FILENAME $request_filename
是核心,确保 PHP 加载的是
/www/wwwroot/your-site.com/v2/index.php
,而非主站的
index.php
若用不同 PHP 版本,需同步改
fastcgi_pass
到对应 socket(如
php-cgi-74.sock
) 如何让 v2 版本正确读取自己的配置和依赖 子目录项目不是“复制粘贴”就能跑,它仍需完整运行环境。常见坑包括:
.env
文件路径错误:Laravel 或 ThinkPHP 默认从
public/
上级找,但
/v2/
下 public 路径变了,需在
v2/index.php
中显式指定:
$_ENV['APP_ENV'] = 'production';
并重载
Dotenv::createImmutable(__DIR__.'/../');
Composer autoload 冲突:主站和
v2/
若共用 vendor,可能加载错类;建议
v2/
单独
composer install
,并确保其
vendor/autoload.php
被正确引入 缓存路径冲突:
storage/
或
runtime/
目录不能共用,否则 v1 写锁会导致 v2 报错;需在
v2/config/app.php
或启动脚本中改写缓存根目录为
../storage-v2/
灰度流量控制的实际操作方式 子目录本身不提供流量比例控制,它只是“入口标识”。真实灰度要结合业务逻辑或前置网关——但在宝塔单机场景下,最简可行方案是: 前端 JS 或 App 根据灰度策略(如用户 ID 取模、cookie 标识)动态拼接 API 基地址:
https://api.example.com/v2/
vs
https://api.example.com/
后端统一网关层(如用 Nginx
map
+
split_clients
)分流到不同 upstream,但这就超出子目录范畴了 更轻量的做法:在主站入口
index.php
中判断请求头或 cookie,用
header('Location: /v2/...')
302 重定向(仅适合低频、非 API 场景) 真正要注意的反而是日志隔离——务必让
v2/
的 PHP 错误日志写入独立文件,否则和主站混在一起根本分不清问题来源。在子目录的
location
块里加上:
fastcgi_param PHP_VALUE "error_log=/www/wwwroot/your-site.com/v2-error.log";

相关文章