Rails+Unicorn+NginxにCapistrano導入

# はじめに
EC2にRails+Unicorn+Nginxの環境を構築した状態で自動デプロイツール`Capistrano`を導入します。

# Capistranoを利用するためのGemをインストール
ローカル環境のGemfileを編集。

```rb:Gemfile
group :development, :test do
  gem 'capistrano'
  gem 'capistrano-rbenv'
  gem 'capistrano-bundler'
  gem 'capistrano-rails'
  gem 'capistrano3-unicorn'
end
```
Gemfileを読み込み。
ローカルのターミナルで以下のコマンド。

```
$ bundle install
$ bundle exec cap install
```
いくつかファイルが生成されます。
・`Capfile`利用するライブラリを指定するファイル
・`deploy.rb、production.rb、staging.rb`デプロイについての設定を書くファイル

# Capfileを編集

```rb:Capfile
require "capistrano/setup"
require "capistrano/deploy"
require 'capistrano/rbenv'
require 'capistrano/bundler'
require 'capistrano/rails/assets'
require 'capistrano/rails/migrations'
require 'capistrano3/unicorn'

Dir.glob("lib/capistrano/tasks/*.rake").each { |r| import r }
```

# デプロイについての設定ファイルを編集
`production.rb`を編集。

```rb:config/deploy/production.rb
server '<Elastic IP>', user: 'ec2-user', roles: %w{app db web}
```

`deploy.rb`を編集。
production環境、staging環境どちらにも当てはまる設定を記述します。
下記のような項目があります。

・アプリケーション名
・gitのレポジトリ
・利用するSCM
・タスク
・それぞれのタスクで実行するコマンド

`config/deploy.rb`を以下のように書き換えます。

```rb:config/deploy.rb

# config valid only for current version of Capistrano
# capistranoのバージョンを記載。固定のバージョンを利用し続け、バージョン変更によるトラブルを防止する
lock '<Capistranoのバージョン>'

# Capistranoのログの表示に利用する
set :application, '<自身のアプリケーション名>'

# どのリポジトリからアプリをpullするかを指定する
set :repo_url,  'git@github.com:<Githubのユーザー名>/<レポジトリ名>.git'

# バージョンが変わっても共通で参照するディレクトリを指定
set :linked_dirs, fetch(:linked_dirs, []).push('log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'vendor/bundle', 'public/system', 'public/uploads')

set :rbenv_type, :user
set :rbenv_ruby, '<このアプリで使用しているrubyのバージョン>' 

# どの公開鍵を利用してデプロイするか
set :ssh_options, auth_methods: ['publickey'],
                  keys: ['<ローカルPCのEC2インスタンスのSSH鍵(pem)へのパス（例：~/.ssh/key_pem.pem）>'] 

# プロセス番号を記載したファイルの場所
set :unicorn_pid, -> { "#{shared_path}/tmp/pids/unicorn.pid" }

# Unicornの設定ファイルの場所
set :unicorn_config_path, -> { "#{current_path}/config/unicorn.rb" }
set :keep_releases, 5

# デプロイ処理が終わった後、Unicornを再起動するための記述
after 'deploy:publishing', 'deploy:restart'
namespace :deploy do
  task :restart do
    invoke 'unicorn:restart'
  end
end
```

Capistranoによる自動デプロイ後のディレクトリ構造が変わるので以下の操作が必要。
# unicorn.rbの記述を編集
以下のように書き換え。

```rb:config/unicorn.rb
app_path = File.expand_path('../../../', __FILE__)

worker_processes 1
# currentを指定
working_directory "#{app_path}/current"

# それぞれ、sharedの中を参照するよう変更
listen "#{app_path}/shared/tmp/sockets/unicorn.sock"
pid "#{app_path}/shared/tmp/pids/unicorn.pid"
stderr_path "#{app_path}/shared/log/unicorn.stderr.log"
stdout_path "#{app_path}/shared/log/unicorn.stdout.log"
```

# Nginxの設定ファイルの記述を編集
EC2サーバー上で操作。

```
$ sudo vim /etc/nginx/conf.d/rails.conf
```

自身の設定ファイルを全て書き換え。
`<>`の中身は自身のものと書き換え必要。

```:rails.conf
upstream app_server {
  # sharedの中を参照するよう変更
  server unix:/var/www/<アプリケーション名>/shared/tmp/sockets/unicorn.sock;
}

server {
  listen 80;
  server_name <Elastic IPを記入>;

  # currentの中を参照するよう変更
  root /var/www/<アプリケーション名>/current/public;

  location ^~ /assets/ {
    gzip_static on;
    expires max;
    add_header Cache-Control public;
    # currentの中を参照するよう変更
    root   /var/www/<アプリケーション名>/current/public;
  }

  try_files $uri/index.html $uri @unicorn;

  location @unicorn {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;
    proxy_pass http://app_server;
  }

  error_page 500 502 503 504 /500.html;
}
```

Nginxの設定を変更したら、再読込・再起動。

```
$ sudo systemctl reload nginx
$ sudo systemctl restart nginx
```

データベースの起動を確認。（サーバー上にDB構築の場合）

```
$ sudo systemctl restart mariadb 
```

unicornのプロセスをkill。

```
$ ps aux | grep unicorn
$ kill <確認したunicorn rails masterのPID>
```

ローカルでの修正を全てmasterにpush。

# 自動デプロイを実行

ローカルのターミナルで以下のコマンド。

```
$ bundle exec cap production deploy
```

無事に完了したらブラウザで確認。
うまくいかなかったらログを確認しましょう。