介绍
在此教程中,我们将演示如何使用 Git 钩子将您的 Rails 应用程序的生产环境自动部署到远程 Ubuntu 14.04 服务器. 使用 Git shooks 将允许您通过简单地将您的更改推向生产服务器来部署您的应用程序,而不是需要手动拉动并执行数据库迁移等操作. 在继续研究应用时,设置某种形式的自动部署,如Git钩子,可以长期节省你的时间.
这个特定的设置使用了一个简单的接收后
Git 绑架,除了 Puma 作为应用程序服务器, Nginx 作为 Puma 的反向代理, PostgreSQL 作为数据库。
如果你是Git Hooks的新手,想在继续前了解更多,请阅读本教程: 如何使用Git Hooks来自动化开发和部署任务。
前提条件
在我们的示例设置中,我们将使用一个名为).如果你想在没有输入密码的情况下部署,请确保设置SSH密钥。
您需要在您的服务器上安装 Ruby. 如果您尚未这样做,您可以使用 rbenv或 RVM与 Rails 一起安装。
您还需要有一个 Rails 应用程序,该应用程序在本地开发机器上的 git 存储库中进行管理. 如果您没有一个,并且想跟进,我们将提供一个简单的示例应用程序。
让我们开始吧!
安装 PostgreSQL
大多数生产 Rails 环境都使用 PostgreSQL 作为数据库,所以现在让我们把它安装在您的服务器上。
在您的生产服务器上,更新 apt-get:
1sudo apt-get update
然后用这些命令安装PostgreSQL:
1sudo apt-get install postgresql postgresql-contrib libpq-dev
注意:你还应该在开发机器上安装 PostgreSQL,这样你就可以本地安装pg
宝石, PostgreSQL 适配器。当我们将宝石添加到你的应用程序的 Gemfile 时,这将被要求运行bundle install
。
创建生产数据库用户
为了让事情简单,让我们将生产数据库用户命名为你的应用程序名称,例如,如果你的应用程序被称为appname
,你应该创建一个 PostgreSQL 用户,如下:
1sudo -u postgres createuser -s appname
我们要设置数据库用户的密码,所以输入 PostgreSQL 控制台如下:
1sudo -u postgres psql
然后为数据库用户设置密码,appname
在示例中,如下:
1\password appname
输入您想要的密码并确认它。
使用此命令退出 PostgreSQL 控制台:
1\q
现在,我们已经准备好将您的应用程序配置为适当的数据库连接信息。
准备您的 Rails 应用程序
在您的开发机器上,最有可能是您的本地计算机上,我们将准备您的应用程序部署。
可选:创建 Rails 应用程序
理想情况下,您已经拥有您想要部署的 Rails 应用程序。如果是这样的情况,您可以跳过此子部分,并在跟进时进行适当的替换。
这些命令将创建一个新的 Rails 应用程序,名为appname
,在我们的主目录中。
1cd ~
2rails new appname
然后转到应用程序目录:
1cd appname
对于我们的样本应用程序,我们将生成一个支架控制器,以便我们的应用程序有显示的东西:
1rails generate scaffold Task title:string note:text
现在让我们确保我们的应用程序处于 git 存储库中。
启动 Git Repo
如果您的应用程序由于某种原因尚未在 Git 存储库中,请初始化并执行初始委托。
在您的开发机器上,切换到您的应用程序目录. 在我们的示例中,我们的应用程序被称为appname
,它位于我们的主目录中:
1cd ~/appname
1git init
2git add -A
3git commit -m 'initial commit'
现在,让我们调整我们的应用程序,以准备它连接到我们的生产PostgreSQL数据库。
更新数据库配置
在您的开发机器上,如果您还没有进入应用程序目录,则更改到您的应用程序目录,在我们的示例中,我们的应用程序称为appname
,并位于我们的主目录中:
1cd ~/appname
现在在你最喜欢的编辑器中打开数据库配置文件,我们会使用‘vi’:
1vi config/database.yml
查找应用程序数据库配置的 production 部分,并用您的生产数据库连接信息替换它. 如果您遵循精确的示例设置,它将看起来像这样的东西(必要时替换任何值):
1[label config/database.yml excerpt]
2production:
3 <<: *default
4 host: localhost
5 adapter: postgresql
6 encoding: utf8
7 database: appname_production
8 pool: 5
9 username: <%= ENV['APPNAME_DATABASE_USER'] %>
10 password: <%= ENV['APPNAME_DATABASE_PASSWORD'] %>
这规定了应用程序的生产环境应该在 localhost — 生产服务器上使用名为appname_production
的 PostgreSQL 数据库. 请注意,数据库用户名和密码设置为环境变量。
更新 Gemfile
如果您的 Gemfile 还没有 PostgreSQL 适配器宝石,‘pg’,以及指定的 Puma 宝石,您应该现在添加它们。
在你最喜欢的编辑器中打开你的应用程序的 Gemfile. We will use vi
here:
1vi Gemfile
向 Gemfile 添加以下行:
1[label Gemfile excerpt]
2group :production do
3 gem 'pg'
4 gem 'puma'
5end
这规定了生产
环境应该使用pg
和puma
宝石。
配置 Puma
在配置Puma之前,您应该查找您的服务器有多少CPU核心,您可以轻松地在您的服务器上使用此命令:
1grep -c processor /proc/cpuinfo
现在,在您的开发机器上,添加Puma配置到config/puma.rb
。
1vi config/puma.rb
复制并粘贴此配置到文件中:
1[label config/puma.rb]
2# Change to match your CPU core count
3workers 2
4
5# Min and Max threads per worker
6threads 1, 6
7
8app_dir = File.expand_path("../..", __FILE__)
9shared_dir = "#{app_dir}/shared"
10
11# Default to production
12rails_env = ENV['RAILS_ENV'] || "production"
13environment rails_env
14
15# Set up socket location
16bind "unix://#{shared_dir}/sockets/puma.sock"
17
18# Logging
19stdout_redirect "#{shared_dir}/log/puma.stdout.log", "#{shared_dir}/log/puma.stderr.log", true
20
21# Set master PID and state locations
22pidfile "#{shared_dir}/pids/puma.pid"
23state_path "#{shared_dir}/pids/puma.state"
24activate_control_app
25
26on_worker_boot do
27 require "active_record"
28 ActiveRecord::Base.connection.disconnect! rescue ActiveRecord::ConnectionNotEstablished
29 ActiveRecord::Base.establish_connection(YAML.load_file("#{app_dir}/config/database.yml")[rails_env])
30end
将工人
的数量改变为您的服务器的CPU内核数量,例如假设您有2个内核。
这将Puma配置为您的应用程序的位置,以及其插槽,日志和PID的位置. 您可以自由地修改文件或添加您需要的任何其他选项。
承诺你的最近的变化:
1git add -A
2git commit -m 'added pg and puma'
在继续前,生成一个秘密密密钥,用于您的应用程序的生产环境:
1rake secret
1[secondary_label rake secret sample output:]
229cc5419f6b0ee6b03b717392c28f5869eff0d136d8ae388c68424c6e5dbe52c1afea8fbec305b057f4b071db1646473c1f9a62f803ab8386456ad3b29b14b89
您将复制输出,并使用它在下一步中设置应用程序的SECRET_KEY_BASE
。
创建 Puma Upstart 脚本
让我们创建一个Upstart init脚本,以便我们可以轻松启动和停止Puma,并确保它在启动时启动。
在您的生产服务器上,从 Puma GitHub 存储库下载 Jungle Upstart 工具到您的主目录:
1cd ~
2wget https://raw.githubusercontent.com/puma/puma/master/tools/jungle/upstart/puma-manager.conf
3wget https://raw.githubusercontent.com/puma/puma/master/tools/jungle/upstart/puma.conf
现在打开所提供的 puma.conf
文件,这样我们就可以配置 Puma 部署用户:
1vi puma.conf
寻找指定setuid
和setgid
的两个行,并用部署用户和组的名称代替应用程序
。
1[label puma.conf excerpt 1 of 2]
2setuid deploy
3setgid deploy
现在,寻找这个行:exec /bin/bash``EOT
。在它下面添加以下行,确保取代PostgreSQL用户名和密码,以及您之前创建的雷克秘密:
1[label puma.conf excerpt 2 of 2]
2 export APPNAME_DATABASE_USER='appname'
3 export APPNAME_DATABASE_PASSWORD='appname_password'
4 export SECRET_KEY_BASE='rake_secret_generated_above'
保存和退出。
现在将脚本复制到Upstart服务目录:
1sudo cp puma.conf puma-manager.conf /etc/init
「puma-manager.conf」脚本引用了它应该管理的应用程序的 `/etc/puma.conf。
1sudo vi /etc/puma.conf
该文件中的每个行都应该是您希望puma-manager
管理的应用程序的路径,我们将我们的应用程序部署到用户主目录中的名为appname
的目录中。
1[label /etc/puma.conf]
2/home/deploy/appname
保存和退出。
现在您的应用程序已配置为在启动时启动,通过Upstart。这意味着您的应用程序即使在您的服务器重新启动后也将启动。
安装和配置 Nginx
为了使应用程序能够访问互联网,我们应该使用 Nginx 作为 Web 服务器。
使用 apt-get 安装 Nginx:
1sudo apt-get install nginx
现在用文本编辑器打开默认服务器块:
1sudo vi /etc/nginx/sites-available/default
用下列代码块替换文件的内容. 请确保用相应的用户名和应用程序名称(两个位置)替换突出部分:
1[label /etc/nginx/sites-available/default]
2upstream app {
3 # Path to Puma SOCK file, as defined previously
4 server unix:/home/deploy/appname/shared/sockets/puma.sock fail_timeout=0;
5}
6
7server {
8 listen 80;
9 server_name localhost;
10
11 root /home/deploy/appname/public;
12
13 try_files $uri/index.html $uri @app;
14
15 location @app {
16 proxy_pass http://app;
17 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
18 proxy_set_header Host $http_host;
19 proxy_redirect off;
20 }
21
22 error_page 500 502 503 504 /500.html;
23 client_max_body_size 4G;
24 keepalive_timeout 10;
25}
这将 Nginx 配置为反向代理,以便HTTP请求通过Unix插件传送到Puma应用程序服务器。
我们将暂时停止重新启动 Nginx,因为该应用程序尚未在服务器上。
准备生产 Git 远程
在您的生产服务器上,安装 git with apt-get:
1sudo apt-get install git
然后为远程存储库创建一个目录. 我们将在主目录中创建一个名为):
1mkdir ~/appname_production
2cd ~/appname_production
3git init --bare
由于这是一个空白的存储库,所以没有工作目录,并且传统设置中的.git 中的所有文件都位于主目录本身。
我们需要创建接收后 git hook,这是在生产服务器接收 git push 时运行的脚本。
1vi hooks/post-receive
将以下脚本复制并粘贴到接收后
文件中:
1[label hooks/post-receive]
2#!/bin/bash
3
4GIT_DIR=/home/deploy/appname_production
5WORK_TREE=/home/deploy/appname
6export APPNAME_DATABASE_USER='appname'
7export APPNAME_DATABASE_PASSWORD='appname_password'
8
9export RAILS_ENV=production
10. ~/.bash_profile
11
12while read oldrev newrev ref
13do
14 if [[ $ref =~ .*/master$ ]];
15 then
16 echo "Master ref received. Deploying master branch to production..."
17 mkdir -p $WORK_TREE
18 git --work-tree=$WORK_TREE --git-dir=$GIT_DIR checkout -f
19 mkdir -p $WORK_TREE/shared/pids $WORK_TREE/shared/sockets $WORK_TREE/shared/log
20
21 # start deploy tasks
22 cd $WORK_TREE
23 bundle install
24 rake db:create
25 rake db:migrate
26 rake assets:precompile
27 sudo restart puma-manager
28 sudo service nginx restart
29 # end deploy tasks
30 echo "Git hooks deploy complete"
31 else
32 echo "Ref $ref successfully received. Doing nothing: only the master branch may be deployed on this server."
33 fi
34done
请确保更新以下突出值:
GIT_DIR
:您之前创建的 bare git 存储库的目录 *WORK_TREE
:您要部署您的应用程序的目录(这应与您在 Puma 配置中指定的位置匹配) *APPNAME_DATABASE_USER
: PostgreSQL 用户名(用于 rake 任务) *APPNAME_DATABASE_PASSWORD
: PostgreSQL 密码(用于 rake 任务)
接下来,您应该查看)时都会运行的命令。
- 运行包装 * 创建数据库 * 迁移数据库 * 预编译资产 * 重新启动 Puma * 重新启动 Nginx
如果您想做出任何更改,或添加错误检查,请在这里这样做。
一旦你完成了收到后脚本的审查,保存和退出。
接下来,使脚本可执行:
1chmod +x hooks/post-receive
没有密码的Sudo
由于接收后链接需要运行 sudo 命令,我们将允许部署用户使用无密码的):
1sudo sh -c 'echo "deploy ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/90-deploy'
这将允许部署
用户在不提供密码的情况下运行sudo
命令. 请注意,您可能希望限制用户可以使用超级用户权限执行的命令。
添加生产 Git 远程
现在我们已经在生产服务器上设置了一切,让我们将生产 git 远程添加到我们的应用程序存储库中。
在您的开发机器上,确保您在您的应用程序目录中:
1cd ~/appname
然后添加一个名为),服务器 IP 地址和远程存储名(appname_production):
1git remote add production deploy@production_server_public_IP:appname_production
现在您的应用程序已经准备好用 git push 部署。
部署到生产
经过所有准备,您现在可以通过运行以下 git 命令将应用程序部署到您的生产服务器:
1git push production master
这只是将您的本地主分支推向您之前创建的远程生产。当生产远程接收推时,它将执行我们之前设置的接收后
连接脚本。
如果您使用了我们的示例应用程序,您应该能够在网页浏览器中访问http://production_server_IP/tasks
并看到这样的东西:
结论
每当你对你的应用程序进行更改时,你可以运行相同的 git push 命令来部署到你的生产服务器上。
本教程只涵盖了)!