You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel多租户应用单容器配置多子域名与环境变量可行性咨询

实现单容器Laravel多租户动态数据库切换(基于子域名)

可以实现,但不能给单个容器配置多个静态环境变量,因为容器的环境变量是启动时固定的。要满足你的需求,核心思路是:通过子域名识别租户,在Laravel运行时动态切换数据库连接,而非依赖容器的静态ENV_VARIABLES。

具体实现步骤

1. 反向代理层处理子域名(以Nginx为例)

单容器需要接收所有子域名的请求,前端需配置Nginx反向代理,解析子域名并传递租户标识到Laravel:

server {
    listen 80;
    # 匹配所有子域名,捕获学校标识
    server_name ~^(?<school>[a-z0-9-]+)\.yourdomain\.com;

    location / {
        proxy_pass http://your-laravel-container:80;
        # 将捕获的学校标识通过请求头传给Laravel
        proxy_set_header X-School $school;
        # 传递原始Host头(可选,Laravel也可直接解析Host获取子域名)
        proxy_set_header Host $host;
    }
}

2. Laravel中编写动态切换数据库的中间件

创建全局中间件,用于识别租户并切换数据库连接:

  1. 生成中间件:
php artisan make:middleware TenantDatabaseMiddleware
  1. 编辑中间件代码(app/Http/Middleware/TenantDatabaseMiddleware.php):
<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\DB;
use Illuminate\Http\Request;

class TenantDatabaseMiddleware
{
    public function handle(Request $request, Closure $next)
    {
        // 从请求头获取学校标识, fallback到解析Host头的子域名
        $schoolIdentifier = $request->header('X-School') ?? explode('.', $request->getHost())[0];
        
        // 可选:验证学校标识合法性,比如从系统配置表查询是否存在
        // $validSchool = \App\Models\School::where('domain_identifier', $schoolIdentifier)->firstOrFail();
        
        // 根据标识拼接数据库名(按你的命名规则调整)
        $databaseName = "school_{$schoolIdentifier}";
        
        // 动态修改数据库连接配置
        Config::set('database.connections.tenant.database', $databaseName);
        // 设置为默认连接,或在模型中指定$connection = 'tenant'
        DB::setDefaultConnection('tenant');
        
        return $next($request);
    }
}
  1. 在app/Http/Kernel.php中注册中间件,加到web或api中间件组:
protected $middlewareGroups = [
    'web' => [
        // ...其他中间件
        \App\Http\Middleware\TenantDatabaseMiddleware::class,
    ],
];

3. 配置Laravel数据库连接

在config/database.php中添加租户专用连接配置(复用基础数据库参数):

'connections' => [
    // ...默认mysql配置
    'tenant' => [
        'driver' => 'mysql',
        'host' => env('DB_HOST', '127.0.0.1'),
        'port' => env('DB_PORT', '3306'),
        'database' => '', // 留空,由中间件动态设置
        'username' => env('DB_USERNAME', 'root'),
        'password' => env('DB_PASSWORD', ''),
        // ...其他配置(charset、collation等)
    ],
],

4. 容器部署注意事项

  • 容器只需设置基础数据库连接环境变量,不需要DB_DATABASE:
    docker run -d \
      -e DB_HOST=your-db-server \
      -e DB_USERNAME=db-user \
      -e DB_PASSWORD=db-pass \
      --name laravel-multitenant \
      your-laravel-image
    
  • 确保数据库服务器允许容器IP访问,且所有学校对应的数据库已提前创建。
  • 若使用Docker Compose,只需在服务配置中声明上述基础环境变量即可。

不推荐的方案:单容器多进程

如果硬要使用不同环境变量的方式,只能在容器内用进程管理器(如supervisord)启动多个Laravel服务实例,每个实例绑定不同子域名和环境变量,但会造成资源浪费,且不符合多租户共用代码库的优雅设计,不建议采用。

内容的提问来源于stack exchange,提问作者Ation

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 05:05:33