原文链接: how-to-deploy-a-rails-app-with-puma-and-nginx-on-ubuntu-14-04
在部署自己的 Rails on Ruby 应用时,有很多有效的安装包可以考虑。这篇教程旨在帮助你用 PostgreSQL 作为数据库,在 Ubuntu14.04 下面使用 Pumma 和 Ngnix 部署 Ruby on Rails 的生产环境。
Puma
是一个应用服务器
(application server),与Passenger
或者Unicon
一样,允许你的RAILS应用
处理并发请求
。由于Puma
不是为用户直接访问而设计,我们需要使用Nginx
作为反向代理
,用于在用户和你的应用之间缓存请求
和响应
。
本教程假设你拥有一台 Ubuntu 14.04 服务器,并在需要部署应用的用户下面安装了以下软件:
- [在 Ubuntu 14.04 上使用 rbenv 安装 Ruby on Rails] [1]
- [在 Ubuntu 14.04 下使用 PostgreSQL 部署 Ruby on Rails] [2]
如果你还没有以上配置,遵循以上链接的教程。我们假设你的用户账号
为 deploy。
以及,这篇教程没有包含 如何配置开发和测试环境。如果你有这方面的需求,遵循 [PostgreSQL with Rails tutorial][2] 中的例子。
理想情况下,你已经有一个想要部署的 Rails 应用。如果是这样,你可以跳过这一节,在接下来使用合适的代替品。如果不是,第一步就是使用 PostgreSQL 作为数据库创建一个新的 Rails 应用。
这个命令将会创建一个新的 Rails 应用,名为appname
.并使用 PostgreSQL 作为数据库。高亮的"appname"可以随便修改:
rails new
appname
-d postgresql
然后跳转到用户目录:
cd
appname
让我们花点时间创建一个PostgreSQL用户
给你的 Rails 应用的生产环境。
为了让事情简单,我们把生产数据库用户名和你的应用名字保持一致。比如,如果你的应用叫做"appname",你就像这样创建 PostgreSQL 用户:
sudo -u postgres createruser -s
appname
我们想要为此数据库用户设置密码,像这样进入 PostgresSQL 控制台:
sudo -u postgres psql
为数据库用户"appname"设置密码:
password appname
输入你想要的密码然后确认。
退出 PostSQL 控制台:
\q
现在我们准备好用这些数据库连接信息配置你的应用了。
确定你是在你的应用的根目录
(cd ~/appname)。
用你喜好的文本编辑器打开你的应用的数据库配置文件。我们用vi
:
vi config/database.yml
更新production
段落,让它看起来像这样:
production:
<<: *default
host: localhost
adapter: postgresql
encoding: utf8
database: appname_production
pool: 5
username: <%= ENV['APPNAME_DATABASE_USER'] %>
password: <%= ENV['APPNAME_DATABASE_PASSWORD'] %>
注意数据库用户名和密码配置成通过环境变量读取,'APPNAME
_DATABASE_USER' 和'APPNAME
_DATABASE_PASSWORD'。这被认为是保证你的生产密码
和密文
(secrets) 在应用代码之外的最佳实践,否则在使用类似 GIT 这样的版本控制系统时容易把它们暴露出去。接下来我们就会介绍 如何配置数据库权限和环境变量。
Save and exit.
在部署 Rails生产应用
(production Rails application) 之前,你需要使用环境变量
设置生产安全密文
(production secret key) 和数据库密码
。作为一种管理环境变量
的简单方式,可以使用 rbenv-vars 插件 来实时加载密码
和密文
到我们的应用里面。
要安装 rbenv-rars 插件,只用跳转到.rbenv/plugins
目录然后 clone it from GitHub. 比如,如果 rbenv 安装在你的home
目录,运行这些命令:
cd ~/.rbenv/plugins
git clone https://github.com/sstephenson/rbenv-vars.git
现在 rbenv-vars 插件已经安装了。让我们来配置需要的环境变量。
首先,生成密文 (secret key),用于校验单个 cookie 的完整性:
cd ~/appname
rake secret
copy 生成的密文 (secret key),然后打开.rbenv-vars 文件:
vi .rbenv-vars
在这里设置的任何环境变量都会被你的 Rails 应用读取。
备注:这里实际是在你的程序根目录里新建一个.rbenv-vars 文件,然后写如环境变量
首先,设置 SECRET_KEY_BASE 变量 (替换高亮部分为你自己刚刚生成并拷贝的密文):
SECRET_KEY_BASE=
your_generated_secret
然后,设置 APPNAME_DATABASE_USER 变量 (替换高亮的'APPNAME'为你自己的应用名称,'appname'是你生产数据库的用户名):
APPNAME
_DATABASE_USER=appname
最后,设置 APPNAME_DATABASE_PASSWORD 变量 (替换高亮的'APPNAME'为你自己的应用名称,'prod_db_pass'是你生产数据库的用户密码):
APPNAME
_DATABASE_PASSWORD=prod_db_pass
Save and exit.
你可以查看那些环境变量被 rbenv-vars 插件设置于你的应用:
rbenv vars
如果你改变你的密文或数据库密码,更新.rbenv-vars 文件。注意保持这个文件的私有性,不要把它包含在你的公开代码库里。
现在你的应用已经配置好可以与你的 PostgreSQL 对话了。让我们来创建数据库:
RAILS_ENV=production rake db:create
如果你依照的是这个例子,我们将生成一个 scaffold controller 这样我们的应用就有点东西可以看了:
rails generate scaffold Task title:string note:text
现在运行命令来更新这个生产数据库:
RAILS_ENV=production rake db:migrate
你还需要预编译assets
:
RAILS_ENV=production rake assets:precompile
要测试你的应用是否工作,可以运行这个生产环境,并绑定你的服务器的公共 IP (替换为你自己的服务器的公共 IP 地址):
RAILS_ENV=production rails server --binding=
server_public_IP
现在到浏览器访问这个 URL:
如果工作正常,你将看到这个页面:
回到你的 Rails server, Ctrl-c 停止应用。
现在准备安装 Puma。
一个简单的办法是把它加入你应用的 Gemfile。打开 Gemfile(确定你是在你的应用的根目录):
vi Gemfile
在文件末尾,加入这一行:
gem 'puma'
Save and exit.
要安装 Puma,以及相关的依赖,run Bundler:
bundle
现在 puma 已经安装了,不过我们还需要配置它。
配置 Puma 之前,你要看一下你的服务器的 CPU 核的数量。用这个命令可以轻易做到:
grep -c processor /proc/cpuinfo
现在加入 Puma 配置到 config/puma.rb
。打开文件:
vi config/puma.rb
拷贝粘贴这些配置到文件里:
# Change to match your CPU core count
workers 2
# Min and Max threads per worker
threads 1, 6
app_dir = File.expand_path("../..", __FILE__)
shared_dir = "#{app_dir}/shared"
# Default to production
rails_env = ENV['RAILS_ENV'] || "production"
environment rails_env
# Set up socket location
bind "unix://#{shared_dir}/sockets/puma.sock"
# Logging
stdout_redirect "#{shared_dir}/log/puma.stdout.log", "#{shared_dir}/log/puma.stderr.log", true
# Set master PID and state locations
pidfile "#{shared_dir}/pids/puma.pid"
state_path "#{shared_dir}/pids/puma.state"
activate_control_app
on_worker_boot do
require "active_record"
ActiveRecord::Base.connection.disconnect! rescue ActiveRecord::ConnectionNotEstablished
ActiveRecord::Base.establish_connection(YAML.load_file("#{app_dir}/config/database.yml")[rails_env])
end
把workers
的数量改为你的服务器的 CPU 核心的数量。
Save and exit. 这会给 puma 配置你应用的位置,Puma 的 socket、logs、PIDs 的位置。可以自由修改这个文件,加入其他你需要的选项。
现在创建配置文件里引用到的目录:
mkdir -p shared/pids shared/sockets shared/log
让我们创建一个 Upstart init script ,这样就能简单的开始和停止 Puma,并确保在服务器启动时同时启动。
从 Puma GitHub 库下载 Jungle Upstart tool 到你的home
目录:
cd ~
wget https://raw.githubusercontent.com/puma/puma/master/tools/jungle/upstart/puma-manager.conf
wget https://raw.githubusercontent.com/puma/puma/master/tools/jungle/upstart/puma.conf
现在打开提供的 puma.conf 文件,这样我们能配置 Puma 开发用户:
vi puma.conf
找到指定setuid
和setuid
的两行,然后用你的开发用户和组的名字替换"apps"。比如,如果你的开发用户叫做"deploy",这几行看起来像这样:
setuid deploy
setgid deploy
Save and exit.
拷贝 scripts 到 Upstart servives 目录:
sudo cp puma.conf puma-manager.conf /etc/init
puma-manager.conf
脚本引用了 它管理的应用的/etc/puma.conf
。现在创建并编辑这个编录文件:
sudo vi /etc/puma.conf
文件里的每一行就是你希望 puma-manager 管理的一个应用的路径。现在加入你的应用的路径。比如:
/home/
deploy
/appname
Save and exit.
现在你的应用已经配置为随服务器引导 (boot time) 而启动。你的应用在你的服务器 reboot 的时候重新启动。
要启动所有被管理的 Puma 应用,运行命令:
sudo start puma-manager
或者你想使用 puma Upstart script 启动单个 Puma 应用:
sudo start puma app=/home/
deploy
/appname
可以使用restart
和stop
来控制应用:
sudo stop puma-manager
sudo restart puma-manager
现在你的 Rails 应用的生产环境运行在 puma 下了,并被shared/sockets/puma.sock
socket 监听。在你的应用被外部用户访问之前,你需要设置 Nginx 反向代理。
使用 apt-get 安装 Nginx :
sudo apt-get install nginx
现在打开默认服务器块:
sudo vi /etc/nginx/sites-available/default
用下面的代码块替换文件内容。确定使用相应的用户名
和应用名字
替换deploy
和appname
部分:
upstream app {
# Path to Puma SOCK file, as defined previously
server unix:/home/deploy/appname/shared/sockets/puma.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;
}
Save and exit.
这个配置 Nginx 作为反向代理,这样 HTTP 请求通过 Unix socket 抵达 Puma 应用服务器。随意修改配置到你感到满意为止。
重启 Nginx 使修改生效:
sudo service nginx restart
现在你的应用的生产环境已经可以通过你的服务器的公共 IP 地址或者 FQDN 访问了。要访问我们之前创建的 Tasks controller,在 web 浏览器里面访问:
你会看到和第一次测试时同样的页面,不过现在被架设在了 nginx 和 Puma 上。
恭喜! 你已经在 Nginx 和 Puma 上部署了你的 Rails on Ruby 应用的生产环境。
如果你希望增强你在生产环境下的 Rails 应用部署的能力,你可以查看系列教程 How To Use Capistrano to Automate Deployments
这个系列基于 CentOS,不过对于自动部署你的应用也有帮助。
[1]: https://ruby-china.org/topics/32449 [2]: https://ruby-china.org/topics/32450