如何在Heroku免费dyno上部署Ruby与PHP双应用?
嘿,我来帮你搞定这个问题!首先得明确一个核心限制:Heroku免费dyno只能运行一个web进程——这就是你没法单独给PHP应用开新web进程的原因。不过别慌,我们可以让同一个web进程同时处理两个应用的请求,下面是两种实用方案,优先推荐第一种(更稳定、内存占用更低):
方案1:用Phusion Passenger统一托管多语言应用
Phusion Passenger是Heroku官方支持的web服务器,原生支持同时运行Ruby、PHP等多语言应用,完美适配你的场景。
步骤1:把Ruby应用的服务器切换为Passenger
在你的Gemfile里添加Passenger依赖:
gem 'passenger'
然后执行更新:
bundle install
修改项目根目录的Procfile,把原来的Ruby服务器(比如Puma)替换成Passenger:
web: passenger start -p $PORT
步骤2:配置Passenger路由规则
在项目根目录创建Passengerfile.json,告诉Passenger把不同路径的请求分发到对应应用:
{ "root": "support/public", // Ruby应用的静态文件根目录 "passenger_app_type": "ruby", "passenger_startup_file": "config.ru", // Ruby应用的入口文件 "locations": { "/billing": { "root": "support/billing/public", // PHP应用的静态文件根目录 "passenger_enabled": true, "passenger_app_type": "php", "passenger_startup_file": "index.php" // PHP应用的入口文件 } } }
如果你的应用目录结构和上面的示例有差异,调整对应的路径即可。
步骤3:让Heroku识别PHP环境
Heroku需要检测到PHP代码才会安装对应的运行环境,所以在项目根目录创建一个空的composer.json文件(即使你的PHP应用没有依赖也没关系):
{ "require": {} }
步骤4:部署到Heroku
提交所有修改并推送:
git add . git commit -m "Set up Passenger for Ruby + PHP co-deployment" git push heroku main
部署完成后,Heroku会自动安装Ruby和PHP的buildpack,Passenger会帮你处理两个应用的请求转发——访问根路径会进入Ruby应用,访问/billing则会进入PHP应用。
方案2:用反向代理(适合不想换服务器的场景)
如果你坚持用原来的Ruby服务器(比如Puma),可以通过反向代理把/billing的请求转发到PHP内置服务器。不过这个方案要注意:免费dyno内存有限,同时跑两个服务器可能会因为内存不足被重启,所以仅作为备选。
步骤1:修改Procfile同时启动两个服务器
web: sh -c "php -S 127.0.0.1:8000 -t support/billing/public & bundle exec puma -p $PORT"
这条命令会先在后台启动PHP内置服务器,再启动Ruby的Puma服务器。
步骤2:添加Rack中间件做请求转发
在Ruby应用中创建一个代理中间件:
# config/middleware/php_proxy.rb class PhpProxy def initialize(app) @app = app @proxy = Rack::Proxy.new end def call(env) if env['PATH_INFO'].start_with?('/billing') # 把/billing前缀去掉,转发给PHP服务器 env['PATH_INFO'].sub!('/billing', '') env['HTTP_HOST'] = '127.0.0.1:8000' @proxy.call(env) else # 其他请求交给Ruby应用处理 @app.call(env) end end end
然后在config.ru中注册这个中间件:
require_relative 'config/middleware/php_proxy' use PhpProxy run Rails.application # 替换成你的Ruby应用入口
步骤3:部署测试
同样提交修改后推送到Heroku即可。
内容的提问来源于stack exchange,提问作者codelearner

