基于Passenger的同域名多版本多Rails应用多租户部署方案问询
Hey there! 很高兴看到你已经上手Rails一个月还搞定了生产环境部署,这个多版本同域名部署的需求确实是Rails开发者常遇到的场景,用Passenger来实现完全可行,我给你梳理几个实用方案和关键步骤:
核心思路:基于Passenger的虚拟主机+路由/标识区分
不管是多版本应用还是多租户场景,核心都是让Passenger根据不同的请求规则,指向对应版本的Rails应用,同时保证各个应用的Ruby/Rails版本互相隔离。
方案1:同域名下通过子路径区分不同应用(比如 example.com/app1、example.com/app2)
这是同域名下最直观的部署方式,以Passenger+Nginx组合为例(也是生产环境最常用的搭配):
前置准备:用rbenv或RVM在VPS上装好所有需要的Ruby版本,给每个Rails应用指定好对应版本(比如在应用目录下执行
rbenv local 2.7.6),并完成bundle install和预编译(rails assets:precompile RAILS_ENV=production)。修改Nginx配置:找到你的域名配置文件(通常在
/etc/nginx/sites-available/your-domain.conf),添加多个location块对应不同子路径:
server { listen 80; server_name example.com; # 第一个应用:Rails 6.1版本,对应子路径 /app1 location /app1 { root /var/www/app1/public; # 应用的public目录路径 passenger_enabled on; # 指定该应用用的Ruby版本(替换成你的rbenv/RVM路径) passenger_ruby /home/your-user/.rbenv/versions/2.7.6/bin/ruby; passenger_app_env production; # 关键配置:告诉Rails这个应用运行在子路径下 passenger_base_uri /app1; } # 第二个应用:Rails 7.0版本,对应子路径 /app2 location /app2 { root /var/www/app2/public; passenger_enabled on; passenger_ruby /home/your-user/.rbenv/versions/3.1.2/bin/ruby; passenger_app_env production; passenger_base_uri /app2; } # 可选:主应用(根路径 /) location / { root /var/www/main-app/public; passenger_enabled on; passenger_ruby /home/your-user/.rbenv/versions/3.0.4/bin/ruby; passenger_app_env production; } }
- 配置Rails子路径支持:每个子路径部署的应用,需要在
config/environments/production.rb里添加前缀配置,避免静态资源404:
# 对应/app1的应用 config.action_controller.relative_url_root = "/app1"
- 重启生效:执行
sudo systemctl restart nginx,之后访问对应的子路径就能看到对应版本的应用了。
方案2:同域名下通过租户标识区分(多租户场景)
如果是多租户需求,希望同一个域名下不同租户访问不同版本的应用,可以通过请求头或URL参数来切换:
- Nginx条件配置:在域名配置里根据请求头(比如
X-Tenant-ID)动态指定应用目录和Ruby版本:
server { listen 80; server_name example.com; # 默认应用配置 set $app_root /var/www/default-app/public; set $ruby_path /home/your-user/.rbenv/versions/3.0.4/bin/ruby; # 根据租户ID切换应用 if ($http_x_tenant_id = "tenant1") { set $app_root /var/www/tenant1-app/public; set $ruby_path /home/your-user/.rbenv/versions/2.7.6/bin/ruby; } if ($http_x_tenant_id = "tenant2") { set $app_root /var/www/tenant2-app/public; set $ruby_path /home/your-user/.rbenv/versions/3.1.2/bin/ruby; } location / { root $app_root; passenger_enabled on; passenger_ruby $ruby_path; passenger_app_env production; # 把租户ID传给Rails应用,方便后续多租户逻辑处理 passenger_env_var TENANT_ID $http_x_tenant_id; } }
- Rails多租户逻辑:在应用里通过
ENV["TENANT_ID"]获取租户标识,实现数据库隔离、资源隔离等多租户功能。
关键注意事项
- 版本隔离:一定要用rbenv/RVM给每个应用绑定独立的Ruby版本,Passenger的
passenger_ruby参数必须指向对应版本的可执行文件,避免版本冲突。 - 权限问题:确保Nginx运行用户(通常是
www-data)对每个应用的public、tmp目录有读写权限,否则会出现500错误。 - SSL适配:如果用HTTPS,只需要在server块里添加SSL证书配置即可,不影响多应用的部署逻辑。
- 进程管理:Passenger会自动为每个应用维护独立的进程池,不用担心不同应用互相干扰。
内容的提问来源于stack exchange,提问作者S. Harper
相关产品推荐
相关产品推荐

