序章

このチュートリアルでは、Gitフックを使用して、Railsアプリケーションの本番環境のリモートUbuntu14.04サーバーへのデプロイを自動化する方法を示します。 Gitフックを使用すると、データベースの移行を手動でプルして実行する必要がなく、変更を本番サーバーにプッシュするだけでアプリケーションをデプロイできます。 アプリケーションで作業を続けると、Gitフックなどの何らかの形式の自動デプロイを設定することで、長期的には時間を節約できます。

この特定のセットアップでは、アプリケーションサーバーとしてのPuma、PumaへのリバースプロキシとしてのNginx、およびデータベースとしてのPostgreSQLに加えて、単純な「受信後」のGitフックを使用します。

Gitフックを初めて使用し、先に進む前に詳細を知りたい場合は、次のチュートリアルをお読みください:Gitフックを使用して開発およびデプロイタスクを自動化する方法

前提条件

Ubuntuサーバーでスーパーユーザー権限を持つroot以外のユーザーにアクセスする必要があります。 セットアップ例では、deployというユーザーを使用します。 このチュートリアルでは、その設定方法を説明します: Ubuntu14.04を使用したサーバーの初期設定。 パスワードを入力せずにデプロイする場合は、必ずSSHキーを設定してください。

サーバーにRubyをインストールする必要があります。 まだインストールしていない場合は、rbenvまたはRVMを使用してRailsと一緒にインストールできます。

また、ローカル開発マシンのgitリポジトリで管理されるRailsアプリケーションが必要になります。 持っておらず、フォローしたい場合は、簡単なサンプルアプリを提供します。

始めましょう!

PostgreSQLをインストールする

ほとんどの本番Rails環境はデータベースとしてPostgreSQLを使用しているので、今すぐサーバーにインストールしましょう。

本番サーバーで、apt-getを更新します。

  1. sudo apt-get update

次に、次のコマンドを使用してPostgreSQLをインストールします。

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

注:PostgreSQLアダプターであるpggemをローカルにインストールできるように、開発マシンにもPostgreSQLをインストールする必要があります。 これは、アプリケーションのGemfileにgemを追加するときに、bundle installを実行するために必要になります。 インストール手順はOSによって異なるため、これは読者に任された演習です。

本番データベースユーザーの作成

簡単にするために、本番データベースのユーザーにアプリケーション名と同じ名前を付けましょう。 たとえば、アプリケーションの名前が「appname」の場合、次のようなPostgreSQLユーザーを作成する必要があります。

  1. sudo -u postgres createuser -s appname

データベースユーザーのパスワードを設定したいので、次のようにPostgreSQLコンソールに入ります。

  1. sudo -u postgres psql

次に、データベースユーザーのパスワード(例では「appname」)を次のように設定します。

  1. \password appname

希望のパスワードを入力して確認します。

次のコマンドでPostgreSQLコンソールを終了します。

  1. \q

これで、適切なデータベース接続情報を使用してアプリケーションを構成する準備が整いました。

Railsアプリケーションを準備する

開発マシン、おそらくローカルコンピューターで、アプリケーションを展開する準備をします。

オプション:Railsアプリケーションを作成する

理想的には、デプロイしたいRailsアプリケーションがすでにあるはずです。 この場合は、このサブセクションをスキップして、フォローしながら適切な置換を行うことができます。 そうでない場合、最初のステップは新しいRailsアプリケーションを作成することです。

これらのコマンドは、ホームディレクトリに「appname」という名前の新しいRailsアプリケーションを作成します。 強調表示された「appname」を他のものに自由に置き換えてください。

  1. cd ~
  2. rails new appname

次に、アプリケーションディレクトリに移動します。

  1. cd appname

サンプルアプリでは、スキャフォールドコントローラーを生成して、アプリケーションに次の情報を表示します。

  1. rails generate scaffold Task title:string note:text

次に、アプリケーションがgitリポジトリにあることを確認しましょう。

Gitリポジトリを初期化する

何らかの理由でアプリケーションがまだGitリポジトリにない場合は、アプリケーションを初期化して初期コミットを実行します。

開発マシンで、アプリケーションのディレクトリに移動します。 この例では、アプリは「appname」と呼ばれ、ホームディレクトリにあります。

  1. cd ~/appname
  1. git init
  2. git add -A
  3. git commit -m 'initial commit'

次に、アプリケーションを微調整して、本番のPostgreSQLデータベースに接続できるように準備します。

データベース構成の更新

開発マシンで、まだそこにいない場合は、アプリケーションのディレクトリに移動します。 この例では、アプリは「appname」と呼ばれ、ホームディレクトリにあります。

  1. cd ~/appname

次に、お気に入りのエディターでデータベース構成ファイルを開きます。 viを使用します:

  1. vi config/database.yml

アプリケーションのデータベース構成のproductionセクションを見つけて、本番データベースの接続情報に置き換えます。 設定された例に正確に従った場合、次のようになります(必要に応じて任意の値に置き換えてください)。

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'] %>

保存して終了。 これは、アプリケーションの本番環境で、ローカルホスト(本番サーバー)で「appname_production」と呼ばれるPostgreSQLデータベースを使用する必要があることを指定します。 データベースのユーザー名とパスワードは環境変数に設定されていることに注意してください。 それらは後でサーバー上で指定します。

Gemfileを更新する

GemfileにPostgreSQLアダプターgem、pg、およびPuma gemが指定されていない場合は、ここで追加する必要があります。

アプリケーションのGemfileをお気に入りのエディターで開きます。 ここではviを使用します。

  1. vi Gemfile

次の行をGemfileに追加します。

Gemfileの抜粋
group :production do
  gem 'pg'
  gem 'puma'
end

保存して終了。 これは、production環境でpgおよびpumaジェムを使用する必要があることを指定します。

Pumaを構成する

Pumaを構成する前に、サーバーに搭載されているCPUコアの数を調べる必要があります。 次のコマンドを使用して、サーバー上で簡単にそれを行うことができます。

  1. grep -c processor /proc/cpuinfo

次に、開発マシンで、Puma構成をconfig/puma.rbに追加します。 テキストエディタでファイルを開きます。

  1. vi config/puma.rb

この構成をコピーしてファイルに貼り付けます。

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

workersの数をサーバーのCPUコアの数に変更します。 この例では、コアが2つあると想定しています。

保存して終了。 これにより、アプリケーションの場所、およびそのソケット、ログ、およびPIDの場所を使用してPumaが構成されます。 ファイルを自由に変更するか、必要な他のオプションを追加してください。

最近の変更をコミットします。

  1. git add -A
  2. git commit -m 'added pg and puma'

次に進む前に、アプリの本番環境で使用される秘密鍵を生成します。

  1. rake secret
rake secret sample output:
29cc5419f6b0ee6b03b717392c28f5869eff0d136d8ae388c68424c6e5dbe52c1afea8fbec305b057f4b071db1646473c1f9a62f803ab8386456ad3b29b14b89

次の手順では、出力をコピーして使用し、アプリケーションのSECRET_KEY_BASEを設定します。

PumaUpstartスクリプトを作成する

Pumaを簡単に起動および停止し、起動時に確実に起動できるように、Upstartinitスクリプトを作成しましょう。

本番サーバーで、JungleUpstartツールをPumaGitHubリポジトリからホームディレクトリにダウンロードします。

  1. cd ~
  2. wget https://raw.githubusercontent.com/puma/puma/master/tools/jungle/upstart/puma-manager.conf
  3. wget https://raw.githubusercontent.com/puma/puma/master/tools/jungle/upstart/puma.conf

次に、提供されたpuma.confファイルを開いて、Pumaデプロイメントユーザーを構成できるようにします。

  1. vi puma.conf

setuidsetgidを指定する2行を探し、「apps」をデプロイメントユーザーとグループの名前に置き換えます。 たとえば、デプロイメントユーザーが「デプロイ」と呼ばれる場合、行は次のようになります。

puma.confの抜粋1/2
setuid deploy
setgid deploy

次に、exec /bin/bash <<'EOT'という行を探します。 その下に次の行を追加します。必ずPostgreSQLのユーザー名とパスワード、および前に作成したrakeシークレットに置き換えてください。

puma.confの抜粋2/2
  export APPNAME_DATABASE_USER='appname'
  export APPNAME_DATABASE_PASSWORD='appname_password'
  export SECRET_KEY_BASE='rake_secret_generated_above'

保存して終了。

次に、スクリプトをUpstartサービスディレクトリにコピーします。

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

puma-manager.confスクリプトは、管理する必要のあるアプリケーションの/etc/puma.confを参照します。 今すぐそのインベントリファイルを作成して編集しましょう:

  1. sudo vi /etc/puma.conf

このファイルの各行は、puma-managerで管理するアプリケーションへのパスである必要があります。 ユーザーのホームディレクトリにある「appname」という名前のディレクトリにアプリケーションを展開します。 この例では、次のようになります(アプリが存在する場所へのパスを必ず更新してください:

/etc/puma.conf
/home/deploy/appname

保存して終了。

これで、アプリケーションは起動時にUpstartを介して起動するように構成されました。 これは、サーバーが再起動された後でもアプリケーションが起動することを意味します。 アプリケーションをデプロイしていないため、まだ開始したくないことに注意してください。

Nginxをインストールして構成する

アプリケーションをインターネットにアクセスできるようにするには、NginxをWebサーバーとして使用する必要があります。

apt-getを使用してNginxをインストールします。

  1. sudo apt-get install nginx

次に、テキストエディタでデフォルトのサーバーブロックを開きます。

  1. sudo vi /etc/nginx/sites-available/default

ファイルの内容を次のコードブロックに置き換えます。 強調表示された部分を適切なユーザー名とアプリケーション名(2つの場所)に置き換えてください。

/ etc / nginx / sites-available / default
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の再起動は控えます。 次にアプリケーションを準備します。

ProductionGitRemoteを準備する

本番サーバーで、apt-getを使用してgitをインストールします。

  1. sudo apt-get install git

次に、リモートリポジトリ用のディレクトリを作成します。 「appname_production」という名前のホームディレクトリに裸のgitリポジトリを作成します。 リモートリポジトリには、自由に名前を付けてください(ただし、~/appnameには、アプリケーションをデプロイする場所であるため、配置しないでください)。

  1. mkdir ~/appname_production
  2. cd ~/appname_production
  3. git init --bare

これはベアリポジトリであるため、作業ディレクトリはなく、従来の設定で.gitにあるすべてのファイルはメインディレクトリ自体にあります。

受信後のgitフックを作成する必要があります。これは、本番サーバーがgitプッシュを受信したときに実行されるスクリプトです。 エディタでhooks/post-receiveファイルを開きます。

  1. 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ユーザー名(レーキタスクに必要)
  • APPNAME_DATABASE_PASSWORD:PostgreSQLパスワード(レーキタスクに必要)

次に、# start deploy tasksコメントと# end deploy tasksコメントの間のコマンドを確認する必要があります。 これらは、マスターブランチが本番gitリモート(appname_production)にプッシュされるたびに実行されるコマンドです。 それらをそのままにしておくと、サーバーはアプリケーションの実稼働環境に対して次のことを実行しようとします。

  • バンドラーを実行する
  • データベースを作成する
  • データベースを移行する
  • アセットをプリコンパイルします
  • Pumaを再起動します
  • Nginxを再起動します

変更を加えたり、エラーチェックを追加したりする場合は、ここで自由に行ってください。

受信後のスクリプトの確認が完了したら、保存して終了します。

次に、スクリプトを実行可能にします。

  1. chmod +x hooks/post-receive

パスワードなしのSudo

post-receiveフックはsudoコマンドを実行する必要があるため、デプロイユーザーがパスワードなしのsudoを使用できるようにします(異なる場合は、ここでデプロイユーザー名に置き換えてください)。

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

これにより、deployユーザーはパスワードを入力せずにsudoコマンドを実行できるようになります。 デプロイユーザーがスーパーユーザー権限で実行できるコマンドを制限したい場合があることに注意してください。 少なくとも、SSHキー認証を使用し、パスワード認証を無効にする必要があります。

ProductionGitRemoteを追加する

本番サーバーですべてがセットアップされたので、本番gitリモートをアプリケーションのリポジトリに追加しましょう。

開発マシンで、アプリケーションのディレクトリにいることを確認してください。

  1. cd ~/appname

次に、本番サーバーで作成したベアgitリポジトリappname_productionを指す「production」という名前の新しいgitリモートを追加します。 ユーザー名(deploy)、サーバーIPアドレス、およびリモートリポジトリ名(appname_production)を置き換えます。

  1. git remote add production deploy@production_server_public_IP:appname_production

これで、アプリケーションをgitpushでデプロイする準備が整いました。

本番環境にデプロイする

準備がすべて完了したら、次のgitコマンドを実行して、アプリケーションを本番サーバーにデプロイできます。

  1. git push production master

これは、ローカルマスターブランチを以前に作成した本番リモートにプッシュするだけです。 本番リモートはプッシュを受信すると、前に設定したpost-receiveフックスクリプトを実行します。 すべてを正しく設定すると、アプリケーションは本番サーバーのパブリックIPアドレスで使用できるようになります。

サンプルアプリケーションを使用した場合は、Webブラウザでhttp://production_server_IP/tasksにアクセスして、次のように表示できるはずです。

Sample Rails App

結論

アプリケーションに変更を加えるときはいつでも、同じgitpushコマンドを実行して本番サーバーにデプロイできます。 これだけで、プロジェクトの全期間にわたって多くの時間を節約できます。

このチュートリアルでは「受信後」フックについてのみ説明しましたが、展開プロセスの自動化を改善するのに役立つフックには他にもいくつかの種類があります。 Gitフックの詳細については、このチュートリアルをお読みください: Gitフックを使用して開発およびデプロイタスクを自動化する方法