在 Ubuntu 14.04 上使用 Capistrano、Nginx 和 Puma 部署 Rails 应用

简介

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

此命令使用 curlhttps://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 dogem 'capistrano',         require: falsegem 'capistrano-rvm',     require: falsegem 'capistrano-rails',   require: falsegem 'capistrano-bundler', require: falsegem 'capistrano3-puma',   require: false
endgem '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: trueset :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 dodesc '为 Puma Pids 和 Socket 创建目录'task :make_dirs doon roles(:app) doexecute "mkdir #{shared_path}/tmp/sockets -p"execute "mkdir #{shared_path}/tmp/pids -p"endendbefore :start, :make_dirs
endnamespace :deploy dodesc "确保本地 git 与远程同步。"task :check_revision doon roles(:app) dounless `git rev-parse HEAD` == `git rev-parse origin/master`puts "警告:HEAD 与 origin/master 不同"puts "运行 `git push` 来同步更改。"exitendendenddesc '初始部署'task :initial doon roles(:app) dobefore 'deploy:restart', 'puma:start'invoke 'deploy'endenddesc '重启应用'task :restart doon roles(:app), in: :sequence, wait: 5 doinvoke 'puma:restart'endendbefore :starting,     :check_revisionafter  :finishing,    :compile_assetsafter  :finishing,    :cleanupafter  :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 SizeRequest 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 以处理高流量负载

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/747233.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Elasticsearch(13) match_phrase的使用

elasticsearch version&#xff1a; 7.10.1 match_phrase 语法 POST <index>/_search {"query": {"match_phrase": {"<field_name>": {"query": "<your_search_phrase>","slop": <max_dis…

第二十五节 Java 继承

继承是所有 OOP 语言和 Java 语言不可缺少的组成部分。 继承是 Java 面向对象编程技术的一块基石&#xff0c;是面向对象的三大特征之一&#xff0c;也是实现软件复用的重要手段&#xff0c;继承可以理解为一个对象从另一个对象获取属性的过程。 如果类 A 是类 B 的父类&…

数据结构--线性表

1.线性表的定义&#xff1a; 存在唯一的一个被称为“第一个”的数据元素&#xff1b; 存在唯一的一个被称为“最后一个”的数据元素&#xff1b; 除第一个之外&#xff0c;集合中的每一个数据元素都只有一个前驱&#xff1b; 除最后一个之外&#xff0c;集合中的每一个数据…

大话设计模式——7.抽象工厂模式(Abstract Factory Pattern)

1.介绍 抽象工厂模式是工厂模式的进一步优化&#xff0c;提供一个创建一系列相关或相互依赖对象的接口&#xff0c;而无需指定它们具体的类。属于创建型模式。 UML图&#xff1a; 2.示例 车辆制造工厂&#xff0c;不仅可以制造轿车也可以用来生产自行车。 1&#xff09;Abs…

算法——异或运算

理解&#xff1a; 1、相同为0&#xff0c;不同为1 2、可以理解为2进制的无进位相加 性质&#xff1a; 1、0 ^ N N N ^ N 0 2、交换律 结合律 a ^ b b ^ a a ^ b ^ c a ^ ( b ^ c ) 用异或实现两个数交换 #include"iostream" using namespace std; int ma…

vivado 逻辑优化约束、功率优化、Vivado Tools电源优化

逻辑优化约束 逻辑保护 Vivado设计套件在逻辑优化过程中尊重DONT_TOUCH属性。确实如此不优化具有这些特性的离开网或单元。为了加快网络选择过程&#xff0c;网络具有DONT_TOUCH的属性被预过滤并且不被考虑用于物理优化。对于有关详细信息&#xff0c;请参阅《Vivado Design …

10、MongoDB -- MongoDB 的 MongoTemplate 的功能和用法介绍

目录 MongoTemplate 的功能和用法演示前提&#xff1a;登录单机模式的 mongodb 服务器命令登录【test】数据库的 mongodb 客户端命令登录【admin】数据库的 mongodb 客户端命令 为 MongoDB 提供的两个 Starterspring-boot-starter-data-mongodb&#xff08;为以同步方式操作 Mo…

C语言:操作符详解(下)

目录 一、逗号表达式二、下标访问[ ]、函数调用()1. [ ]下标引用操作符2.函数调用操作符 三、结构成员访问操作符1.结构体(1) 结构的声明(2) 结构体变量的定义和初始化 2.结构成员访问操作符(1)结构体成员的直接访问(2)结构体成员的间接访问 四、操作符的属性&#xff1a;优先级…

<个人笔记>数论

1.快速幂 (1)求解问题&#xff1a; 给定 n组 ai,bi,pi求 aibi mod pi 的值。 (2)主要思想&#xff1a;任何一个数(b)&#xff0c;可以被 n 个 2k 相加获得。 即 b 2k1 2k2 2k3 … 2logb。 快速幂模板&#xff1a; typedef long long LL;LL qmi(int a,int b,int p){LL re…

深入理解JMM

一、什么是JMM JMM&#xff08;java memory model&#xff09;Java内存模型&#xff1a;是java虚拟机规范中定义的一组规范&#xff0c;用于屏蔽掉各种硬件和操作系统的内存访问差异&#xff0c;以实现让JAVA程序在各平台都能达到一致的并发结果。其主要规定了线程和内存之间的…

对称加密算法(DES、AES)

加密密钥 解密密钥 DES现在基本不再使用 3DES处理速度慢 AES通常用于移动通信系统加密以及基于SSH协议的软件

c++入门你需要知道的知识点(上)

&#x1fa90;&#x1fa90;&#x1fa90;欢迎来到程序员餐厅&#x1f4ab;&#x1f4ab;&#x1f4ab; 今日主菜&#xff1a;c入门 主厨&#xff1a;邪王真眼 所属专栏&#xff1a;c专栏 主厨的主页&#xff1a;Chef‘s blog 前言&#xff1a; 咱也是好久没有更…

Leet code 1658 将x减到0的最小操作数

解题思路&#xff1a;滑动窗口 主要思想&#xff1a;正难逆简 题目需要左找一个数 右找一个数 我们不如直接找中间最长的一连串子数让这串子树和为 数组子树和减去X 找不到就返回 -1 滑动窗口双指针从左端出发&#xff0c;进行 进窗口 判断 出窗口 更新结果四个步骤 代码…

python文件的打开及open方法

打开文件 方法1&#xff1a; 使用try/except/finally 例子&#xff1a; try:data_in open(rD:\TEST\a.txt,encodingutf-8)print(data_in.readlines(),end)except IOError:print(File Error occured!)finally:data_in.close() 结果&#xff1a; [这是一个测试文件。\n, 文…

C++ Qt里如何使用std::thread

本篇博客介绍如何在C++ Qt项目里使用std::thread,以及父子线程之间的交互方法。 怎么编写多线程代码 很多C++开发者困惑如何使用多线程,其实主要是在做项目时是否有多任务的场景,如果没有则不需要使用到多线程,用一个客户端开发的场景来解释一下如何使用多线程,例如开发一…

防火墙中的SNAT 与DNAT

SNAT&#xff1a;让内网机器可以访问外网服务器 DNAT:让外网机器可以访问内网服务器 SNAT的原理 源地址转换&#xff0c;根据指定条件修改数据包的源IP地址&#xff0c;通常被叫做源映射 数据包从内网发送到公网时&#xff0c;SNAT会把数据包的源IP由私网IP转换成公网IP 当响应…

JAVA 100道题目(2)

2.创建一个程序&#xff0c;接受用户输入的字符串并检查它是否为回文。 以下是一个简单的Java程序&#xff0c;它接受用户输入的字符串并检查该字符串是否为回文&#xff08;正读和反读都相同的字符串&#xff09;&#xff1a; java复制代码 import java.util.Scanner; public…

with open----bug

with open(os.path.join(output_path, "closed_rel_paths.jsonl"), "w") as f: # 打开文件&#xff0c;准备写入闭合关系路径for head in tqdm(rdict.rel2idx): # 遍历头部关系paths set() # 初始化路径集合if head "None" or "inv_&q…

【JetsonNano】onnxruntime-gpu 环境编译和安装,支持 Python 和 C++ 开发

1. 设备 2. 环境 sudo apt-get install protobuf-compiler libprotoc-devexport PATH/usr/local/cuda/bin:${PATH} export CUDA_PATH/usr/local/cuda export cuDNN_PATH/usr/lib/aarch64-linux-gnu export CMAKE_ARGS"-DONNX_CUSTOM_PROTOC_EXECUTABLE/usr/bin/protoc&qu…

在Java中如何将十进制转换为二进制,八进制,十六进制以及它们之间的互相转换

目录 一、算法实现进制之间的转换 &#xff08;1&#xff09;十进制转换为二进制 &#xff08;2&#xff09;二进制转换成十进制 二、Java中的API实现进制转换 &#xff08;1&#xff09;十进制转换为二进制 &#xff08;2&#xff09;十进制转换为八进制 &#xff08;3…