在Nginx和Unicorn上运行多个Rails应用程序

10

我成功地使用Screencast 335上的VPS部署教程搭建了一个rails网站。现在我想在一个新的域名下添加另一个rails应用程序,但是我对所需步骤感到困惑。

在上述设置中,sites-available或/etc/nginx/nginx.conf没有进行任何更改。唯一的配置在我的应用程序配置目录中的unicorn.rb、unicorn_init.sh和nginx.conf文件中。nginx.conf文件如下所示:

upstream unicorn {
  server unix:/tmp/unicorn.my_app.sock fail_timeout=0;
}
server {
  listen 80 default deferred;
  # server_name my_app.com.au www.my_app.com.au;
  root /var/www/my_app/current/public;
  location ^~ /assets/ {
    gzip_static on;
    expires max;
    add_header Cache-Control public;
  }
  try_files $uri/index.html $uri @unicorn;
  location @unicorn {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;
    proxy_pass http://unicorn;
  }
  error_page 500 502 503 504 /500.html;
  client_max_body_size 4G;
  keepalive_timeout 10;
}

在我的 Capistrano 配方中,我有这一行

sudo "ln -nfs #{current_path}/config/nginx.conf /etc/nginx/sites-enabled/#{application}"

添加第二个域名只需要在 listen 后面删除默认的 deferred ,取消注释 server_name 部分,然后使用不同的 upstream socket 名称和服务器名称重复此配置文件来完成吗?这样做可行吗,还是我需要将此文件转移到 sites-available 并创建一个到 sites-enabled 的符号链接?

3个回答

21
在unicorn.rb文件中:
应用程序1:
root = "/var/www/application_1/current"
working_directory root
pid "#{root}/tmp/pids/unicorn-app1.pid"
listen "/tmp/unicorn.app1.sock"

应用程序 2:

root = "/var/www/application_2/current"
working_directory root
pid "#{root}/tmp/pids/unicorn-app2.pid"
listen "/tmp/unicorn.app2.sock"

在nginx.conf中:
应用程序1:
upstream app1_server {
  server unix:/tmp/unicorn.app1.sock fail_timeout=0;
}

server {
  listen 80;
  server_name my_app_1.com www.my_app_1.com;
  root /var/www/app1/current/public;

  location ^~ /assets/ {
    gzip_static on;
    expires max;
    add_header Cache-Control public;
  }

  try_files $uri/index.html $uri @app1_server;
  location @app1_server {
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header Host $http_host;
  proxy_redirect off;
  proxy_pass http://app1_server;
 }

  error_page 500 502 503 504 /500.html;
  client_max_body_size 4G;
  keepalive_timeout 10;
}

应用程序2:

upstream app2_server {
  # point to app2 sock
  server unix:/tmp/unicorn.app2.sock fail_timeout=0;
}

server {
  listen 80;
  server_name my_app_2.com www.my_app_2.com;
  root /var/www/app2/current/public;

  location ^~ /assets/ {
    gzip_static on;
    expires max;
    add_header Cache-Control public;
  }

  try_files $uri/index.html $uri @app2_server;
  location @app2_server {
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header Host $http_host;
  proxy_redirect off;
  proxy_pass http://app2_server;
 }

  error_page 500 502 503 504 /500.html;
  client_max_body_size 4G;
  keepalive_timeout 10;
}

你好!我正在使用与您相同的设置,但卡在了正确设置unicorn部分。您可以分享一下您的deploy.rb文件吗?另外,您是否在使用RVM?您是如何解决部署中的“wrapper”部分的呢? - oFca
无法编辑它,因为只有一个字符不同,但我认为在App2的nginx.conf文件中,您应该引用app2.sock文件而不是app1。 - Tyrone Wilson
2
每个nginx.conf文件的端口号不应该是唯一的吗? - Uchenna
独角兽 shell 脚本怎么样,init.d 中的那个?在我的设置中,它已经硬编码了一个 APP_ROOT,并指向第一个应用程序。我需要为第二个应用程序创建另一个 shell 脚本吗? - Kocur4d

4
我在这里回答了一个我自己提出的问题: Multiple Rails 4 app using nginx + unicorn
但以下是答案:
我使用Ruby 2.0Rails 4.0。我假设您已经安装了nginx和unicorn。所以,让我们开始吧!
在您的nginx.conf文件中,我们将使nginx指向一个unicorn套接字:
upstream unicorn_socket_for_myapp {
  server unix:/home/coffeencoke/apps/myapp/current/tmp/sockets/unicorn.sock fail_timeout=0;
}

然后,在你的服务器监听80端口的情况下,添加一个指向Rails应用子目录的位置块(此代码必须在服务器块内):

location /myapp/ {
    try_files $uri @unicorn_proxy;
  }

  location @unicorn_proxy {
    proxy_pass http://unix:/home/coffeencoke/apps/myapp/current/tmp/sockets/unicorn.sock;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;
    proxy_set_header X-Forwarded-Proto $scheme;
  }

现在你可以将Unicorn作为一个守护进程使用:
sudo unicorn_rails -c config/unicorn.rb -D

最后一件要做的事情,也是我最喜欢的一件事情,就是为Rails路由文件添加作用域,像这样:

MyApp::Application.routes.draw do
  scope '/myapp' do
    root :to => 'welcome#home'

    # other routes are always inside this block
    # ...
  end
end

这样,你的应用程序将映射一个链接 /myapp/welcome,而不仅仅是 /welcome
但是有一种更好的方法。
嗯,在生产服务器上可以使用上述方法,但是在开发过程中怎么办?难道你要正常开发,然后在部署时更改 Rails 配置吗?对于每个应用程序都需要这样做吗?这是不必要的。
因此,你需要创建一个新的模块,放在lib/route_scoper.rb中:
require 'rails/application'

module RouteScoper
  def self.root
    Rails.application.config.root_directory
  rescue NameError
    '/'
  end
end

之后,在你的routes.rb文件中添加以下内容:
require_relative '../lib/route_scoper'

MyApp::Application.routes.draw do
  scope RouteScoper.root do
    root :to => 'welcome#home'

    # other routes are always inside this block
    # ...
  end
end

我们正在做的是检查是否已指定根目录,如果指定了,则使用它,否则前往“/”。现在我们只需要在config/environments/production.rb中指定根目录即可。
MyApp::Application.configure do
  # Contains configurations for the production environment
  # ...

  # Serve the application at /myapp
  config.root_directory = '/myapp'
end

在config/enviroments/development.rb文件中,我没有指定config.root_directory。这样它将使用正常的url根目录。

聪明,我喜欢你的方法 :-) - patm
感谢提供示例,是否有可能创建关于此的短视频教程? - Nezir

4
使用Nginx和Unicorn在一个主机上托管不同的应用程序非常容易。每个应用程序的socket文件定义不同的名称可以获得分离。当然,您应该在nginx.conf的server部分中指向正确的current/public目录。最后一步是在unicorn_init.sh文件中:在顶部,您应该使用应用程序当前/公共目录的完整路径更改APP_ROOT。 如果您的设置类似于RailsCast,所有其他事情都由capistrano完成。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接