前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >如何在Ubuntu 14.04上使用Git Hooks部署Rails应用程序

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

原创
作者头像
楠宝宝
修改2018-09-26 17:17:13
2.5K0
修改2018-09-26 17:17:13
举报

介绍

在本教程中,我们将向您展示如何使用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:

代码语言:javascript
复制
sudo apt-get update

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

代码语言:javascript
复制
sudo apt-get install postgresql postgresql-contrib libpq-dev

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

创建生产数据库用户

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

代码语言:javascript
复制
sudo -u postgres createuser -s appname

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

代码语言:javascript
复制
sudo -u postgres psql

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

代码语言:javascript
复制
\password appname

输入所需的密码并确认。

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

代码语言:javascript
复制
\q

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

准备你的Rails应用程序

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

可选:创建Rails应用程序

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

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

代码语言:javascript
复制
cd ~
rails new appname

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

代码语言:javascript
复制
cd appname

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

代码语言:javascript
复制
rails generate scaffold Task title:string note:text

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

初始化Git Repo

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

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

代码语言:javascript
复制
cd ~/appname
git init
git add -A
git commit -m 'initial commit'

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

更新数据库配置

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

代码语言:javascript
复制
cd ~/appname

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

代码语言:javascript
复制
vi config/database.yml

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

代码语言:javascript
复制
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

代码语言:javascript
复制
vi Gemfile

将以下行添加到Gemfile:

代码语言:javascript
复制
group :production do
  gem 'pg'
  gem 'puma'
end

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

配置Puma

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

代码语言:javascript
复制
grep -c processor /proc/cpuinfo

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

代码语言:javascript
复制
vi config/puma.rb

将此配置复制并粘贴到文件中:

代码语言:javascript
复制
# 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的位置。随意修改文件,或添加您需要的任何其他选项。

提交您最近的更改:

代码语言:javascript
复制
git add -A
git commit -m 'added pg and puma'

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

代码语言:javascript
复制
rake secret
rake secret sample output:29cc5419f6b0ee6b03b717392c28f5869eff0d136d8ae388c68424c6e5dbe52c1afea8fbec305b057f4b071db1646473c1f9a62f803ab8386456ad3b29b14b89

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

创建Puma Upstart脚本

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

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

代码语言:javascript
复制
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部署用户了:

代码语言:javascript
复制
vi puma.conf

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

代码语言:javascript
复制
setuid deploy
setgid deploy

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

代码语言:javascript
复制
  export APPNAME_DATABASE_USER='appname'
  export APPNAME_DATABASE_PASSWORD='appname_password'
  export SECRET_KEY_BASE='rake_secret_generated_above'

保存并退出。

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

代码语言:javascript
复制
sudo cp puma.conf puma-manager.conf /etc/init

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

代码语言:javascript
复制
sudo vi /etc/puma.conf

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

代码语言:javascript
复制
/home/deploy/appname

保存并退出。

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

安装和配置Nginx

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

使用apt-get安装Nginx:

代码语言:javascript
复制
sudo apt-get install nginx

现在使用文本编辑器打开默认服务器块:

代码语言:javascript
复制
sudo vi /etc/nginx/sites-available/default

使用以下代码块替换文件的内容。请务必使用适当的用户名和应用程序名称(两个位置)替换deploy/appname的部分:

代码语言:javascript
复制
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:

代码语言:javascript
复制
sudo apt-get install git

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

代码语言:javascript
复制
mkdir ~/appname_production
cd ~/appname_production
git init --bare

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

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

代码语言:javascript
复制
vi hooks/post-receive

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

代码语言:javascript
复制
#!/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

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

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

接下来,使脚本可执行:

代码语言:javascript
复制
chmod +x hooks/post-receive

无密码的Sudo

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

代码语言:javascript
复制
sudo sh -c 'echo "deploy ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/90-deploy'

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

添加Production Git Remote

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

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

代码语言:javascript
复制
cd ~/appname

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

代码语言:javascript
复制
git remote add production deploy@production_server_public_IP:appname_production

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

部署到生产

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

代码语言:javascript
复制
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》

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

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 介绍
  • 准备
  • 安装PostgreSQL
    • 创建生产数据库用户
    • 准备你的Rails应用程序
      • 可选:创建Rails应用程序
        • 初始化Git Repo
          • 更新数据库配置
            • 更新Gemfile
              • 配置Puma
              • 创建Puma Upstart脚本
              • 安装和配置Nginx
              • 准备生产Git Remote
                • 无密码的Sudo
                • 添加Production Git Remote
                • 部署到生产
                • 结论
                相关产品与服务
                云数据库 PostgreSQL
                腾讯云数据库 PostgreSQL(TencentDB for PostgreSQL,云 API 使用 postgres 作为简称)能够让您在云端轻松设置、操作和扩展目前功能最强大的开源数据库 PostgreSQL。腾讯云将负责绝大部分处理复杂而耗时的管理工作,如 PostgreSQL 软件安装、存储管理、高可用复制、以及为灾难恢复而进行的数据备份,让您更专注于业务程序开发。
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档