如何在Ubuntu 14.04上使用Git Hooks部署Rails应用程序

介绍

在本教程中,我们将向您展示如何使用Git hooks自动将Rails应用程序的生产环境部署到远程Ubuntu 14.04服务器。使用Git hooks将允许您通过简单地将更改推送到生产服务器来部署应用程序,而不必手动拉动并执行诸如执行数据库迁移之类的操作。当您继续处理应用程序时,设置某种形式的自动部署(例如Git hooks)将为您节省时间。

这个特殊的设置使用简单的“post-receive”Git hooks,除了Puma作为应用服务器,Nginx作为Puma的反向代理,PostgreSQL作为数据库。

准备

  • 您将需要访问在Ubuntu服务器上具有超级用户权限的非root用户。在我们的教程设置中,我们将使用一个名为deploy的用户。如果要在不输入密码的情况下进行部署,请务必设置SSH密钥。没有服务器的同学可以在这里购买,不过我个人更推荐您使用免费的腾讯云开发者实验室进行试验,学会安装后再购买服务器
  • 您需要在服务器上安装Ruby。
  • 您还需要一个在本地开发机器上的git存储库中管理的Rails应用程序。如果您没有并希望跟进,我们将提供一个简单的示例应用程序。

让我们开始吧!

安装PostgreSQL

大多数生产Rails环境使用PostgreSQL作为数据库,所以现在让我们将它安装在您的服务器上。

生产服务器上,更新apt-get:

sudo apt-get update

然后使用以下命令安装PostgreSQL:

sudo apt-get install postgresql postgresql-contrib libpq-dev

注意:您还应该在开发计算机上安装PostgreSQL,这样您就可以在本地安装pggem,PostgreSQL适配器。当我们将gem添加到应用程序的Gemfile时,需要运行此bundle install命令。由于安装步骤因操作系统而异,因此这是留给读者的练习。

创建生产数据库用户

为了简单起见,我们将生产数据库用户命名设为与您的应用程序名称相同。例如,如果您的应用程序名为“appname”,则应创建一个PostgreSQL用户,如下所示:

sudo -u postgres createuser -s appname

我们想设置数据库用户的密码,所以进入PostgreSQL控制台,如下所示:

sudo -u postgres psql

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

\password appname

输入所需的密码并确认。

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

\q

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

准备你的Rails应用程序

在您的开发机器上,很可能是您的本地计算机,我们将准备您要部署的应用程序。

可选:创建Rails应用程序

理想情况下,您已经拥有了要部署的Rails应用程序。如果是这种情况,您可以跳过此小节,并在跟随时进行适当的替换。如果没有,第一步是创建一个新的Rails应用程序。

这些命令将在我们的主目录中创建一个名为“appname”的新Rails应用程序。随意替换“appname”为其他名字:

cd ~
rails new appname

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

cd appname

对于我们的示例应用程序,我们将生成一个脚手架控制器,以便我们的应用程序可以显示:

rails generate scaffold Task title:string note:text

现在让我们确保我们的应用程序位于git存储库中。

初始化Git Repo

如果您的应用程序由于某种原因尚未存在于Git存储库中,请初始化它并执行初始提交。

开发计算机上,切换到应用程序的目录。在我们的示例中,我们的应用程序名为“appname”,它位于我们的主目录中:

cd ~/appname
git init
git add -A
git commit -m 'initial commit'

现在让我们调整我们的应用程序,准备连接到我们的生产PostgreSQL数据库。

更新数据库配置

在您的开发计算机上,如果您还没有,请更改到您的应用程序目录。在我们的示例中,我们的应用程序名为“appname”,它位于我们的主目录中:

cd ~/appname

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

vi config/database.yml

查找应用程序数据库配置的生产部分,并将其替换为生产数据库连接信息。如果您完全按照示例设置,它看起来像这样(替换任何适当的值):

production:
  <<: *default
  host: localhost
  adapter: postgresql
  encoding: utf8
  database: appname_production
  pool: 5
  username: <%= ENV['APPNAME_DATABASE_USER'] %>
  password: <%= ENV['APPNAME_DATABASE_PASSWORD'] %>

保存并退出。这指定应用程序的生产环境应该在localhost-生产服务器上使用名为“appname_production”的PostgreSQL数据库。请注意,数据库用户名和密码设置为环境变量。我们稍后会在服务器上指定它们。

更新Gemfile

如果你的Gemfile还没有指定PostgreSQL适配器gem, pg和指定了Puma gem,你应该立即添加它们。

在您喜欢的编辑器中打开应用程序的Gemfile。我们将在这里使用vi

vi Gemfile

将以下行添加到Gemfile:

group :production do
  gem 'pg'
  gem 'puma'
end

保存并退出。这指定production环境应该使用pgpuma gems。

配置Puma

在配置Puma之前,您应该查找服务器具有的CPU核心数。您可以使用此命令轻松地在服务器上执行此操作:

grep -c processor /proc/cpuinfo

现在,在您的开发计算机上,在config/puma.rb中添加Puma配置。在文本编辑器中打开文件:

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

更改服务器的CPU核心数workers。该示例假设您有2个核心。

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

提交您最近的更改:

git add -A
git commit -m 'added pg and puma'

在继续之前,生成一个将用于应用程序生产环境的密钥:

rake secret
rake secret sample output:29cc5419f6b0ee6b03b717392c28f5869eff0d136d8ae388c68424c6e5dbe52c1afea8fbec305b057f4b071db1646473c1f9a62f803ab8386456ad3b29b14b89

您将复制输出并使用它在下一步中设置应用程序的SECRET_KEY_BASE

创建Puma Upstart脚本

让我们创建一个Upstart 初始化脚本,这样我们就可以轻松启动和停止Puma,并确保它在启动时启动。

生产服务器上,从Puma GitHub存储库下载Jungle Upstart工具到您的主目录:

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

寻找指定的两行setuidsetgid,并与您的部署用户和组的名称替换“应用程序”。例如,如果您的部署用户名为“deploy”,则行应如下所示:

setuid deploy
setgid deploy

现在寻找这行:exec /bin/bash <<'EOT'。在其下添加以下行,确保替换PostgreSQL用户名和密码,以及您之前创建的rake密码:

  export APPNAME_DATABASE_USER='appname'
  export APPNAME_DATABASE_PASSWORD='appname_password'
  export SECRET_KEY_BASE='rake_secret_generated_above'

保存并退出。

现在将脚本复制到Upstart服务目录:

sudo cp puma.conf puma-manager.conf /etc/init

puma-manager.conf脚本引用了它应该管理的应用程序/etc/puma.conf。我们现在创建并编辑该库存文件:

sudo vi /etc/puma.conf

此文件中的每一行都应该是您要用puma-manager管理的应用程序的路径。我们将把我们的应用程序部署到用户主目录中名为“appname”的目录中。在我们的示例中,它将是以下内容(请务必更新应用程序所在的路径):

/home/deploy/appname

保存并退出。

现在,您的应用程序配置为在启动时通过Upstart启动。这意味着即使在重新启动服务器后,您的应用程序也会启动。请记住,我们尚未部署应用程序,因此我们暂时还不想启动它。

安装和配置Nginx

为了使应用程序可以访问Internet,我们应该使用Nginx作为Web服务器。

使用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;
}

保存并退出。这将Nginx配置为反向代理,因此HTTP请求通过Unix接口转发到Puma应用程序服务器。您可以根据需要随意进行任何更改。

我们暂时不会重启Nginx,因为服务器上还没有应用程序。我们接下来准备申请。

准备生产Git Remote

生产服务器上,使用apt-get安装git:

sudo apt-get install git

然后为远程存储库创建一个目录。我们将在主目录中创建一个名为“appname_production”的裸git存储库。随意将您的远程存储库命名为您想要的任何名称(除非不将其放入~/appname,因为这是我们将应用程序部署到的地方):

mkdir ~/appname_production
cd ~/appname_production
git init --bare

由于这是一个裸存储库,因此没有工作目录,并且传统设置中位于.git中的所有文件都在主目录中。

我们需要创建post-receive git hook,这是在生产服务器收到git push时将运行的脚本。在编辑器中打开文件hooks/post-receive

vi hooks/post-receive

将以下脚本复制并粘贴到post-receive文件中:

#!/bin/bash

GIT_DIR=/home/deploy/appname_production
WORK_TREE=/home/deploy/appname
export APPNAME_DATABASE_USER='appname'
export APPNAME_DATABASE_PASSWORD='appname_password'

export RAILS_ENV=production
. ~/.bash_profile

while read oldrev newrev ref
do
    if [[ $ref =~ .*/master$ ]];
    then
        echo "Master ref received.  Deploying master branch to production..."
        mkdir -p $WORK_TREE
        git --work-tree=$WORK_TREE --git-dir=$GIT_DIR checkout -f
        mkdir -p $WORK_TREE/shared/pids $WORK_TREE/shared/sockets $WORK_TREE/shared/log

        # start deploy tasks
        cd $WORK_TREE
        bundle install
        rake db:create
        rake db:migrate
        rake assets:precompile
        sudo restart puma-manager
        sudo service nginx restart
        # end deploy tasks
        echo "Git hooks deploy complete"
    else
        echo "Ref $ref successfully received.  Doing nothing: only the master branch may be deployed on this server."
    fi
done

请务必更新以下突出显示的值:

  • GIT_DIR:您之前创建的裸git存储库的目录
  • WORK_TREE:您要将应用程序部署到的目录(这应该与您在Puma配置中指定的位置匹配)
  • APPNAME_DATABASE_USER:PostgreSQL用户名(rake任务需要)
  • APPNAME_DATABASE_PASSWORD:PostgreSQL密码(rake任务需要)

接下来,您应该查看# start deploy tasks# end deploy tasks注释之间的命令。这些是每次将主分支推送到生产git remote(appname_production)时将运行的命令。如果保持原样,服务器将尝试对应用程序的生产环境执行以下操作:

  • 运行bundler
  • 创建数据库
  • 迁移数据库
  • 预编译资产
  • 重启Puma
  • 重启Nginx

如果您想进行任何更改或添加错误检查,请随时在此处执行此操作。

完成查看接收后脚本后,保存并退出。

接下来,使脚本可执行:

chmod +x hooks/post-receive

无密码的Sudo

因为post-receive hook需要运行sudo命令,我们将允许deploy用户使用无密码sudo(如果不同,请在此处替换您的部署用户名):

sudo sh -c 'echo "deploy ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/90-deploy'

这将允许deploy用户在不提供密码的情况下运行sudo命令。请注意,您可能希望限制部署用户可以使用超级用户权限运行的命令。您至少需要使用SSH密钥身份验证并禁用密码身份验证。

添加Production Git Remote

现在我们已经在生产服务器上设置了所有内容,让我们将生产git remote添加到我们的应用程序的存储库中。

开发计算机上,确保您位于应用程序的目录中:

cd ~/appname

然后添加一个名为“production”的新git远程,它指向您在生产服务器上创建的裸git存储库appname_production。替换用户名(部署),服务器IP地址和远程存储库名称(appname_production):

git remote add production deploy@production_server_public_IP:appname_production

现在您的应用程序已准备好使用git push进行部署。

部署到生产

完成所有准备工作后,您现在可以通过运行以下git命令将应用程序部署到生产服务器:

git push production master

这只是将您的本地主分支推送到您之前创建的生产远程中。当生产远程接收推送时,它将执行我们之前设置的post-receivehook脚本。如果正确设置了所有内容,现在应该可以在生产服务器的公共IP地址上使用您的应用程序。

如果您使用我们的示例应用程序,您应该能够在Web浏览器中访问http://production_server_IP/tasks并看到如下内容:

结论

每次对应用程序进行更改时,都可以运行相同的git push命令来部署到生产服务器。仅此一项就可以在项目的整个生命周期中为您节省大量时间。

本教程仅介绍了“post-receive”hook,但还有其他几种类型的挂钩可以帮助改善部署过程的自动化。

想要了解更多关于Linux开源信息教程,请前往腾讯云+社区学习更多知识。

参考文献:《How To Deploy a Rails App with Git Hooks on Ubuntu 14.04》

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

编辑于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏云计算教程系列

如何在Ubuntu 14.04上使用Unicorn和Nginx部署Rails应用程序

当您准备部署Ruby on Rails应用程序时,需要考虑许多有效的设置。本教程将帮助您部署Ruby 在 Rails应用程序中的生产环境,使用PostgreSQ...

920
来自专栏云计算教程系列

如何在Ubuntu 14.04上安装Munin监视工具

Munin是一个系统,网络和基础设施监控应用程序,通过Web浏览器以图形形式提供信息。它是围绕客户端 - 服务器架构设计的,可以配置为监控它所安装的机器(Mun...

1160
来自专栏fixzd

redis系列:主从复制

这篇文章主要讲述Redis的主从复制功能。会依次从环境搭建、功能测试和原理分析几个方面进行介绍。

1454
来自专栏CaiRui

linux基础命令

1.mkdir 创建目录   mkdir -p 循环创建目录   touch 创建文件 2.ls 显示目录或文件   ls -ld=ll 以长目录式查看   l...

2898
来自专栏雨过天晴

原 PHPStrom 9系列激活码

1954
来自专栏黑泽君的专栏

【MyEclipse】我们导入的jar包后, 一般没有关联源码, 需要手动进行关联!推荐这种方式。

1125
来自专栏小樱的经验随笔

Linux目录结构

Linux 目录结构 装完Linux,首先需要弄清Linux 标准目录结构 ? / root —?启动Linux时使用的一些核心文件。如操作系统内核、引导程序G...

4526
来自专栏Java后端技术栈

使用Redis存储Nginx+Tomcat负载均衡集群的Session

环境:Cent OS 7.0(虚拟机环境)、Nginx 1.9.8、Redis 3.2.1

1092
来自专栏Jackson0714

无法获得锁 /var/lib/dpkg/lock - open (11: 资源临时不可用)

5743
来自专栏腾讯云Elasticsearch Service

Elasticsearch跨集群数据迁移之离线迁移

用户在腾讯云上自建的ES集群或者在其它云厂商购买的ES集群,如果要迁移至腾讯云ES,用户可以根据自己的业务需要选择适合自己的迁移方案。如果业务可以停服或者可以暂...

3.2K9

扫码关注云+社区

领取腾讯云代金券