在 Ubuntu 14.04 上使用 Capistrano、Nginx 和 Puma 部署 Rails 应用
Rails 是一个用 Ruby 编写的开源 Web 应用程序框架。它遵循“约定优于配置”的理念,通过假设有一种“最佳”做事方式,让你在不必浏览无尽的配置文件的情况下编写更少的代码,同时实现更多功能。Nginx 是一个高性能的 HTTP 服务器、反向代理和负载均衡器,以其并发性、稳定性、可扩展性和低内存消耗而闻名。与 Nginx 类似,Puma 是另一个极快且并发性能出色的 Web 服务器,具有非常
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。
简介
Rails 是一个用 Ruby 编写的开源 Web 应用程序框架。它遵循“约定优于配置”的理念,通过假设有一种“最佳”做事方式,让你在不必浏览无尽的配置文件的情况下编写更少的代码,同时实现更多功能。
Nginx 是一个高性能的 HTTP 服务器、反向代理和负载均衡器,以其并发性、稳定性、可扩展性和低内存消耗而闻名。与 Nginx 类似,Puma 是另一个极快且并发性能出色的 Web 服务器,具有非常小的内存占用,专为 Ruby Web 应用程序而构建。
Capistrano 是一个远程服务器自动化工具,主要专注于 Ruby Web 应用程序。它通过在 SSH 上编写任意工作流程并自动化常见任务(如资源预编译和重启 Rails 服务器)来可靠地将 Web 应用程序部署到任意数量的远程机器上。
在本教程中,我们将在 DigitalOcean Ubuntu Droplet 上安装 Ruby 和 Nginx,并在我们的 Web 应用程序中配置 Puma 和 Capistrano。Nginx 将用于捕获客户端请求并将其传递给运行 Rails 的 Puma Web 服务器。我们将使用 Capistrano 自动化常见部署任务,因此每当我们需要将新版本的 Rails 应用程序部署到服务器上时,我们可以通过几个简单的命令来完成。
先决条件
要按照本教程操作,您必须具备以下条件:
- Ubuntu 14.04 x64 Droplet
- 一个名为
deploy
的非 root 用户,具有 sudo 权限(《使用 Ubuntu 14.04 进行初始服务器设置》解释了如何设置此权限。) - 托管在远程 git 仓库中准备部署的工作中的 Rails 应用程序
可选地,为了提高安全性,您可以禁用 SSH 的 root 登录,并按照《使用 Ubuntu 14.04 进行初始服务器设置》中的说明更改 SSH 端口号。
本教程中的所有命令都应该以 deploy
用户身份运行。如果命令需要 root 访问权限,则会在命令之前加上 sudo
。
步骤 1 — 安装 Nginx
一旦 VPS 安全,我们就可以开始安装软件包。更新软件包索引文件:
sudo apt-get update
然后,安装 Nginx:
sudo apt-get install curl git-core nginx -y
步骤 2 — 安装数据库
安装您将在 Rails 应用程序中使用的数据库。由于有很多数据库可供选择,我们不会在本指南中涵盖它们。您可以在这里查看主要数据库的说明:
- MySQL
- PostgreSQL
- MongoDB
还要确保查看:
- 《如何在 Ubuntu 14.04 上使用 MySQL 与您的 Ruby on Rails 应用程序》
- 《如何在 Ubuntu 14.04 上使用 PostgreSQL 与您的 Ruby on Rails 应用程序》
步骤 3 — 安装 RVM 和 Ruby
我们不会直接安装 Ruby。相反,我们将使用 Ruby 版本管理器。有很多选择(rbenv、chruby 等),但在本教程中我们将使用 RVM。RVM 允许您轻松在同一系统上安装和管理多个 Ruby,并根据您的应用程序使用正确的 Ruby。当您需要升级 Rails 应用程序以使用更新的 Ruby 时,这将大大简化生活。
在安装 RVM 之前,您需要导入 RVM GPG 密钥:
gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
然后安装 RVM 来管理我们的 Rubies:
curl -sSL https://get.rvm.io | bash -s stable
此命令使用 curl
从 https://get.rvm.io
下载 RVM 安装脚本。-sSL
选项由三个标志组成:
-s
告诉 curl 以“静默模式”下载文件-S
告诉 curl 如果失败则显示错误消息-L
告诉 curl 在检索安装脚本时遵循所有 HTTP 重定向
下载完成后,脚本被 管道 到 bash
。-s
选项将 stable
作为参数传递给 RVM 安装脚本,以下载并安装 RVM 的稳定版本。
我们需要加载 RVM 脚本(作为函数)以便开始使用它。然后我们需要运行 requirements
命令来自动安装 RVM 和 Ruby 正常运行所需的依赖和文件:
source ~/.rvm/scripts/rvm
rvm requirements
现在我们可以安装我们选择的 Ruby。我们将安装最新的 Ruby 2.2.1
(在撰写本文时)作为我们的默认 Ruby:
rvm install 2.2.1
rvm use 2.2.1 --default
第四步 — 安装 Rails 和 Bundler
一旦 Ruby 安装完成,我们就可以开始安装 Rubygems。我们将首先安装 Rails gem,这将允许您的 Rails 应用程序运行,然后我们将安装 bundler
,它可以读取您应用程序的 Gemfile
并自动安装所有所需的 gems。
要安装 Rails 和 Bundler:
gem install rails -V --no-ri --no-rdoc
gem install bundler -V --no-ri --no-rdoc
使用了三个标志:
-V
(详细输出):打印有关 Gem 安装的详细信息--no-ri
- (跳过 Ri 文档):不安装 Ri 文档,节省空间并加快安装速度--no-rdoc
- (跳过 RDocs):不安装 RDocs,节省空间并加快安装速度
第五步 — 设置 SSH 密钥
由于我们希望进行平稳的部署,我们将使用 SSH 密钥进行授权。首先与 GitHub、Bitbucket 或任何其他托管 Rails 应用程序代码库的 Git 远程进行握手:
ssh -T git@github.com
ssh -T git@bitbucket.org
如果收到“Permission denied (publickey)”消息,不用担心。现在,为您的服务器生成 SSH 密钥(公钥/私钥对):
ssh-keygen -t rsa
将新创建的公钥(~/.ssh/id_rsa.pub
)添加到您的代码库的部署密钥中:
- Github 指令
- Bitbucket 指令
如果所有步骤都完成正确,现在您应该能够在不输入密码的情况下通过 SSH 协议 clone
您的 git 仓库:
git clone git@example.com:username/appname.git
如果您需要一个用于测试的示例应用程序,您可以 fork 以下专门为本教程创建的测试应用程序:GitHub 上的示例 Rails 应用程序
git clone
命令将创建一个与您的应用程序同名的目录。例如,将创建一个名为 testapp_rails
的目录。
我们只是克隆以检查我们的部署密钥是否起作用,我们不需要每次推送新更改时都克隆或拉取我们的仓库。我们将让 Capistrano 为我们处理所有这些。如果您愿意,现在可以删除此克隆的目录。
在本地计算机上打开终端。如果您的本地计算机没有 SSH 密钥,请为其创建一个。在本地终端会话中:
ssh-keygen -t rsa
将您的本地 SSH 密钥添加到您的 Droplet 的 Authorized Keys 文件(记得用您的自定义端口号替换端口号):
cat ~/.ssh/id_rsa.pub | ssh -p your_port_num deploy@your_server_ip 'cat >> ~/.ssh/authorized_keys'
第六步 — 在 Rails 应用程序中添加部署配置
在本地计算机上,为您的 Rails 应用程序创建 Nginx 和 Capistrano 的配置文件。首先在 Rails 应用程序的 Gemfile
中添加以下行:
group :development do
gem 'capistrano', require: false
gem 'capistrano-rvm', require: false
gem 'capistrano-rails', require: false
gem 'capistrano-bundler', require: false
gem 'capistrano3-puma', require: false
end
gem 'puma'
使用 bundler
安装您在 Gemfile
中指定的 gems。输入以下命令来捆绑您的 Rails 应用程序:
bundle
捆绑后,运行以下命令配置 Capistrano:
cap install
这将创建:
Capfile
在您的 Rails 应用程序的根目录中deploy.rb
文件在config
目录中deploy
目录在config
目录中
用以下内容替换您的 Capfile
的内容:
# Load DSL and Setup Up Stages
require 'capistrano/setup'
require 'capistrano/deploy'
require 'capistrano/rails'
require 'capistrano/bundler'
require 'capistrano/rvm'
require 'capistrano/puma'
# Loads custom tasks from `lib/capistrano/tasks' if you have any defined.
Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r }
这个 Capfile
加载了一些预定义的任务到您的 Capistrano 配置文件中,使您的部署变得轻松无忧,例如自动:
- 选择正确的 Ruby
- 预编译资源
- 将您的 Git 仓库克隆到正确的位置
- 在您的 Gemfile 更改时安装新的依赖项
用以下内容替换 config/deploy.rb
的内容,并用您的应用程序和 Droplet 参数更新标记为红色的字段:
```markdown
# 更改这些
server 'your_server_ip', port: your_port_num, roles: [:web, :app, :db], primary: true
set :repo_url, 'git@example.com:username/appname.git'
set :application, 'appname'
set :user, 'deploy'
set :puma_threads, [4, 16]
set :puma_workers, 0
# 除非你知道你在做什么,否则不要更改这些
set :pty, true
set :use_sudo, false
set :stage, :production
set :deploy_via, :remote_cache
set :deploy_to, "/home/#{fetch(:user)}/apps/#{fetch(:application)}"
set :puma_bind, "unix://#{shared_path}/tmp/sockets/#{fetch(:application)}-puma.sock"
set :puma_state, "#{shared_path}/tmp/pids/puma.state"
set :puma_pid, "#{shared_path}/tmp/pids/puma.pid"
set :puma_access_log, "#{release_path}/log/puma.error.log"
set :puma_error_log, "#{release_path}/log/puma.access.log"
set :ssh_options, { forward_agent: true, user: fetch(:user), keys: %w(~/.ssh/id_rsa.pub) }
set :puma_preload_app, true
set :puma_worker_timeout, nil
set :puma_init_active_record, true # 当不使用 ActiveRecord 时更改为 false
## 默认值:
# set :scm, :git
# set :branch, :master
# set :format, :pretty
# set :log_level, :debug
# set :keep_releases, 5
## 链接的文件和目录(默认为无):
# set :linked_files, %w{config/database.yml}
# set :linked_dirs, %w{bin log tmp/pids tmp/cache tmp/sockets vendor/bundle public/system}
namespace :puma do
desc '为 Puma Pids 和 Socket 创建目录'
task :make_dirs do
on roles(:app) do
execute "mkdir #{shared_path}/tmp/sockets -p"
execute "mkdir #{shared_path}/tmp/pids -p"
end
end
before :start, :make_dirs
end
namespace :deploy do
desc "确保本地 git 与远程同步。"
task :check_revision do
on roles(:app) do
unless `git rev-parse HEAD` == `git rev-parse origin/master`
puts "警告:HEAD 与 origin/master 不同"
puts "运行 `git push` 来同步更改。"
exit
end
end
end
desc '初始部署'
task :initial do
on roles(:app) do
before 'deploy:restart', 'puma:start'
invoke 'deploy'
end
end
desc '重启应用'
task :restart do
on roles(:app), in: :sequence, wait: 5 do
invoke 'puma:restart'
end
end
before :starting, :check_revision
after :finishing, :compile_assets
after :finishing, :cleanup
after :finishing, :restart
end
# ps aux | grep puma # 获取 puma pid
# kill -s SIGUSR2 pid # 重启 puma
# kill -s SIGTERM pid # 停止 puma
这个 deploy.rb
文件包含了一些合理的默认设置,可以立即使用,帮助你管理应用程序的发布,并在进行部署时自动执行一些任务:
- 使用
production
作为 Rails 应用程序的默认环境 - 自动管理应用程序的多个发布版本
- 使用优化的 SSH 选项
- 检查你的 git 远程是否是最新的
- 管理应用程序的日志
- 在管理 Puma 工作进程时,在内存中预加载应用程序
- 在完成部署后启动(或重新启动)Puma服务器
- 在你的发布中的特定位置打开到 Puma 服务器的套接字
你可以根据自己的需求更改所有选项。现在,需要配置 Nginx。在你的 Rails 项目目录中创建 config/nginx.conf
,并添加以下内容(再次替换为你的参数):
upstream puma {
server unix:///home/deploy/apps/appname/shared/tmp/sockets/appname-puma.sock;
}
server {
listen 80 default_server deferred;
# server_name example.com;
root /home/deploy/apps/appname/current/public;
access_log /home/deploy/apps/appname/current/log/nginx.access.log;
error_log /home/deploy/apps/appname/current/log/nginx.error.log info;
location ^~ /assets/ {
gzip_static on;
expires max;
add_header Cache-Control public;
}
try_files $uri/index.html $uri @puma;
location @puma {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://puma;
}
error_page 500 502 503 504 /500.html;
client_max_body_size 10M;
keepalive_timeout 10;
}
与之前的文件类似,这个 nginx.conf
包含了可以立即使用的默认设置,与你的 deploy.rb
文件中的配置相匹配。它在端口 80 上监听流量,并将请求传递到你的 Puma 套接字,在你的应用程序的 ‘current’ 发布中写入 nginx 日志,压缩所有资产并在浏览器中以最大到期时间进行缓存,将公共文件夹中的 HTML 页面作为静态文件提供,并设置默认的最大 Client Body Size
和 Request Timeout
值。
## 第7步 — 部署你的 Rails 应用程序
如果你正在使用自己的 Rails 应用程序,请提交你刚刚做的更改,并从本地机器推送它们到远程:
```command
git add -A
git commit -m "设置 Puma、Nginx 和 Capistrano"
git push origin master
再次从本地机器进行首次部署:
cap production deploy:initial
这将把你的 Rails 应用程序推送到 Droplet,安装应用程序所需的所有 gem,并启动 Puma web 服务器。这可能需要 5-15 分钟,具体时间取决于你的应用程序使用的 gem 数量。在此过程中,你将看到调试消息。
如果一切顺利,我们现在准备将你的 Puma web 服务器连接到 Nginx 反向代理。
在 Droplet 上,将 nginx.conf
创建符号链接到 sites-enabled
目录:
sudo rm /etc/nginx/sites-enabled/default
sudo ln -nfs "/home/deploy/apps/appname/current/config/nginx.conf" "/etc/nginx/sites-enabled/appname"
重新启动 Nginx 服务:
sudo service nginx restart
现在,你应该能够将你的 Web 浏览器指向你的服务器 IP,并看到你的 Rails 应用程序在运行!
普通部署
每当你对应用程序进行更改并希望将新版本部署到服务器时,请提交更改,像往常一样推送到你的 git 远程,并运行 deploy
命令:
git add -A
git commit -m "部署消息"
git push origin master
cap production deploy
结论
到目前为止,你应该在 Droplet 上运行一个带有 Puma 作为 Web 服务器的 Rails 应用程序,同时 Nginx 和 Capistrano 配置了基本设置。现在,你应该查看其他文档,以帮助你优化配置,以充分发挥你的 Rails 应用程序的潜力:
- Puma 配置
- Capistrano 中的 Puma DSL
- Capistrano 中的本地资源预编译
- 基于 RAM 自动重启 Puma 工作进程
- 优化 Nginx 以处理高流量负载
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)