如何在Ubuntu14.04上使用Unicorn和Nginx部署Rails应用程序

来自菜鸟教程
跳转至:导航、​搜索

介绍

当您准备好部署 Ruby on Rails 应用程序时,需要考虑许多有效的设置。 本教程将帮助您在 Ubuntu 14.04 上使用 Unicorn 和 Nginx 部署 Ruby on Rails 应用程序的生产环境,以 PostgreSQL 作为数据库。

Unicorn 是一个应用服务器,如 PassengerPuma,它使您的 Rails 应用程序能够同时处理请求。 由于 Unicorn 不是为用户直接访问而设计的,我们将使用 Nginx 作为反向代理来缓冲用户和 Rails 应用程序之间的请求和响应。

先决条件

本教程假设您在将部署应用程序的用户上安装了以下软件的 Ubuntu 14.04 服务器:

如果您还没有设置,请按照上面链接的教程进行操作。 我们将假设您的用户名为 deploy

此外,本教程不包括如何设置您的开发或测试环境。 如果您需要这方面的帮助,请按照 PostgreSQL with Rails 教程中的示例进行操作。

创建 Rails 应用程序

理想情况下,您已经有一个要部署的 Rails 应用程序。 如果是这种情况,您可以跳过本节,并在继续进行时进行适当的替换。 如果没有,第一步是创建一个使用 PostgreSQL 作为其数据库的新 Rails 应用程序。

此命令将创建一个名为“appname”的新 Rails 应用程序,它将使用 PostgreSQL 作为数据库。 随意将突出显示的“appname”替换为其他内容:

rails new appname -d postgresql

然后切换到应用程序目录:

cd appname

让我们花点时间创建一个 PostgreSQL 用户,供 Rails 应用程序的生产环境使用。

创建生产数据库用户

为简单起见,让我们将生产数据库用户命名为与您的应用程序名称相同。 例如,如果您的应用程序名为“appname”,您应该像这样创建一个 PostgreSQL 用户:

sudo -u postgres createuser -s appname

我们要设置数据库用户的密码,所以像这样进入 PostgreSQL 控制台:

sudo -u postgres psql

然后设置数据库用户的密码,示例中为“appname”,如下所示:

\password appname

输入您想要的密码并确认。

使用以下命令退出 PostgreSQL 控制台:

\q

现在我们已准备好使用正确的数据库连接信息配置您的应用程序。

配置数据库连接

确保您位于应用程序的根目录 (cd ~/appname)。

在您喜欢的文本编辑器中打开应用程序的数据库配置文件。 我们将使用 vi:

vi config/database.yml

default 部分下,找到显示“pool: 5”的行并在其下添加以下行(如果它尚不存在):

  host: localhost

如果滚动到文件底部,您会注意到 production 部分设置如下:

  username: appname
  password: <%= ENV['APPNAME_DATABASE_PASSWORD'] %>

如果您的生产用户名与您之前创建的数据库用户不匹配,请立即设置。

请注意,数据库密码配置为由环境变量 APPNAME_DATABASE_PASSWORD 读取。 将生产密码和机密保存在应用程序代码库之外被认为是最佳实践,因为如果您使用的是 Git 等分布式版本控制系统,它们很容易暴露。 接下来我们将介绍如何使用环境变量设置数据库身份验证。

安装 rbenv-vars 插件

在部署生产 Rails 应用程序之前,您应该使用环境变量设置生产密钥和数据库密码。 管理环境变量的一种简单方法是使用 rbenv-vars 插件,我们可以使用它在运行时将密码和机密加载到我们的应用程序中。

要安装 rbenv-vars 插件,只需切换到 .rbenv/plugins 目录并从 GitHub 克隆它。 例如,如果 rbenv 安装在您的主目录中,请运行以下命令:

cd ~/.rbenv/plugins
git clone https://github.com/sstephenson/rbenv-vars.git

设置环境变量

现在安装了 rbenv-vars 插件,让我们设置所需的环境变量。

首先,生成密钥,用于验证签名 cookie 的完整性:

cd ~/appname
rake secret

复制生成的密钥,然后使用您喜欢的编辑器打开 .rbenv-vars 文件。 我们将使用 vi:

vi .rbenv-vars

您在此处设置的任何环境变量都可以被您的 Rails 应用程序读取。

首先,像这样设置 SECRET_KEY_BASE 变量(将突出显示的文本替换为您刚刚生成并复制的密钥):

SECRET_KEY_BASE=your_generated_secret

接下来,像这样设置 APPNAME_DATABASE_PASSWORD 变量(将突出显示的“APPNAME”替换为您的应用程序名称,将“prod_db_pass”替换为您的生产数据库用户密码):

APPNAME_DATABASE_PASSWORD=prod_db_pass

保存并退出。

您可以通过运行以下命令查看使用 rbenv-vars 插件为您的应用程序设置的环境变量:

rbenv vars

如果您更改密码或数据库密码,请更新您的 .rbenv-vars 文件。 请注意将此文件保密,不要将其包含在任何公共代码存储库中。

创建生产数据库

现在您的应用程序已配置为与您的 PostgreSQL 数据库通信,让我们创建生产数据库:

RAILS_ENV=production rake db:create

生成控制器

如果您按照示例进行操作,我们将生成一个脚手架控制器,以便我们的应用程序可以查看一些内容:

rails generate scaffold Task title:string note:text

现在运行这个命令来更新生产数据库:

RAILS_ENV=production rake db:migrate

预编译资产

此时,应用程序应该可以工作,但您需要预编译其资产,以便加载任何图像、CSS 和脚本。 为此,请运行以下命令:

RAILS_ENV=production rake assets:precompile

测试申请

要测试您的应用程序是否正常工作,您可以运行生产环境,并将其绑定到服务器的公共 IP 地址(替换您服务器的公共 IP 地址):

RAILS_ENV=production rails server --binding=server_public_IP

现在在 Web 浏览器中访问此 URL:

http://server_public_IP:3000/tasks

如果它工作正常,你应该看到这个页面:

返回到您的 Rails 服务器,然后按 Ctrl-c 停止应用程序。

安装独角兽

现在我们准备安装 Unicorn。

一个简单的方法是将它添加到应用程序的 Gemfile 中。 在您喜欢的编辑器中打开 Gemfile(确保您位于应用程序的根目录中):

vi Gemfile

在文件末尾,使用以下行添加 Unicorn gem:

gem 'unicorn'

保存并退出。

要安装 Unicorn 和任何未完成的依赖项,请运行 Bundler:

bundle

Unicorn 现在已经安装好了,但是我们需要对其进行配置。

配置独角兽

让我们将 Unicorn 配置添加到 config/unicorn.rb。 在文本编辑器中打开文件:

vi config/unicorn.rb

将此配置复制并粘贴到文件中:

# set path to application
app_dir = File.expand_path("../..", __FILE__)
shared_dir = "#{app_dir}/shared"
working_directory app_dir


# Set unicorn options
worker_processes 2
preload_app true
timeout 30

# Set up socket location
listen "#{shared_dir}/sockets/unicorn.sock", :backlog => 64

# Logging
stderr_path "#{shared_dir}/log/unicorn.stderr.log"
stdout_path "#{shared_dir}/log/unicorn.stdout.log"

# Set master PID location
pid "#{shared_dir}/pids/unicorn.pid"

保存并退出。 这会为 Unicorn 配置应用程序的位置,以及其套接字、日志和 PID 的位置。 随意修改文件,或添加您需要的任何其他选项。

现在创建配置文件中引用的目录:

mkdir -p shared/pids shared/sockets shared/log

创建独角兽初始化脚本

让我们创建一个初始化脚本,以便我们可以轻松地启动和停止 Unicorn,并确保它会在启动时启动。

创建一个脚本并使用此命令打开它以进行编辑(如果您愿意,请将突出显示的部分替换为您的应用程序名称):

sudo vi /etc/init.d/unicorn_appname

将以下代码块复制并粘贴到其中,并确保将 USERAPP_NAME(突出显示)替换为适当的值:

#!/bin/sh

### BEGIN INIT INFO
# Provides:          unicorn
# Required-Start:    $all
# Required-Stop:     $all
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: starts the unicorn app server
# Description:       starts unicorn using start-stop-daemon
### END INIT INFO

set -e

USAGE="Usage: $0 <start|stop|restart|upgrade|rotate|force-stop>"

# app settings
USER="deploy"
APP_NAME="appname"
APP_ROOT="/home/$USER/$APP_NAME"
ENV="production"

# environment settings
PATH="/home/$USER/.rbenv/shims:/home/$USER/.rbenv/bin:$PATH"
CMD="cd $APP_ROOT && bundle exec unicorn -c config/unicorn.rb -E $ENV -D"
PID="$APP_ROOT/shared/pids/unicorn.pid"
OLD_PID="$PID.oldbin"

# make sure the app exists
cd $APP_ROOT || exit 1

sig () {
  test -s "$PID" && kill -$1 `cat $PID`
}

oldsig () {
  test -s $OLD_PID && kill -$1 `cat $OLD_PID`
}

case $1 in
  start)
    sig 0 && echo >&2 "Already running" && exit 0
    echo "Starting $APP_NAME"
    su - $USER -c "$CMD"
    ;;
  stop)
    echo "Stopping $APP_NAME"
    sig QUIT && exit 0
    echo >&2 "Not running"
    ;;
  force-stop)
    echo "Force stopping $APP_NAME"
    sig TERM && exit 0
    echo >&2 "Not running"
    ;;
  restart|reload|upgrade)
    sig USR2 && echo "reloaded $APP_NAME" && exit 0
    echo >&2 "Couldn't reload, starting '$CMD' instead"
    $CMD
    ;;
  rotate)
    sig USR1 && echo rotated logs OK && exit 0
    echo >&2 "Couldn't rotate logs" && exit 1
    ;;
  *)
    echo >&2 $USAGE
    exit 1
    ;;
esac

保存并退出。 这将允许您使用 service unicorn_appname 来启动和停止 Unicorn 和 Rails 应用程序。

更新脚本的权限并让 Unicorn 在启动时启动:

sudo chmod 755 /etc/init.d/unicorn_appname
sudo update-rc.d unicorn_appname defaults

让我们现在开始吧:

sudo service unicorn_appname start

现在您的 Rails 应用程序的生产环境在 Unicorn 下运行,它正在侦听 shared/sockets/unicorn.sock 套接字。 在外部用户可以访问您的应用程序之前,您必须设置 Nginx 反向代理。

安装和配置 Nginx

使用 apt-get 安装 Nginx:

sudo apt-get install nginx

现在使用文本编辑器打开默认服务器块:

sudo vi /etc/nginx/sites-available/default

用以下代码块替换文件的内容。 请务必将突出显示的部分替换为适当的用户名和应用程序名称:

upstream app {
    # Path to Unicorn SOCK file, as defined previously
    server unix:/home/deploy/appname/shared/sockets/unicorn.sock fail_timeout=0;
}

server {
    listen 80;
    server_name localhost;

    root /home/deploy/appname/public;

    try_files $uri/index.html $uri @app;

    location @app {
        proxy_pass http://app;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;
    }

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

保存并退出。 这将 Nginx 配置为反向代理,因此 HTTP 请求通过 Unix 套接字转发到 Unicorn 应用程序服务器。 随意进行任何您认为合适的更改。

重新启动 Nginx 以使更改生效:

sudo service nginx restart

现在可以通过服务器的公共 IP 地址或 FQDN 访问 Rails 应用程序的生产环境。 要访问我们之前创建的 Tasks 控制器,请在 Web 浏览器中访问您的应用程序服务器:

http://server_public_IP/tasks

您应该看到您第一次测试应用程序时看到的相同页面,但现在它通过 Nginx 和 Unicorn 提供服务。

结论

恭喜! 您已经使用 Nginx 和 Unicorn 部署了 Ruby on Rails 应用程序的生产环境。

如果您希望改进生产 Rails 应用程序部署,您应该查看我们关于 如何使用 Capistrano 自动化部署 的教程系列。 该系列基于 CentOS,但在自动化部署方面仍应有所帮助。