Rails5.1.2 + Webpacker + ReactをCapstranoでデプロイする手順書①

# 前書き
Webpackerを使い、フロントReact、APPサーバRailsとしたWebサービスをデプロイするためCapistranoを利用しました。
今回は、EC2へCapistranoを利用してデプロイし、サービスが公開されるまでを手順書としてまとめます。

# ローカル手順
ローカルではデプロイの準備のため、CapistranoとUnicornの設定を行います。
## Capistrano設定
### 手順
- Capistranoインストール
- 設定ファイル作成、編集

### Capistranoインストール
Gemfileに以下を記載し、bundle installを行います。

```
 gem 'capistrano'
 gem 'capistrano-bundler'
 gem 'capistrano-rails'
 gem 'capistrano-rbenv'
```

インストールはこれで完了です。

### 設定ファイル作成、編集
下記のコマンドで

- Capfile
- config/deploy/production.rb
- config/deploy/staging.rb
- config/deploy.rb
- lib/capistrano/tasks/task.rb

以上５ファイルが作成されます。
一番下のtask.rbはディレクトリまでが自動で、ファイルは手動で追加します。

```bash
$ bundle exec cap install
```

それぞれ作成されるファイルを説明すると以下のような感じです。

- Capfile
  - Capistrano全体の設定ファイル(Capistranoのプラグインのrequireなどを記述する)
- config/deploy/production.rb
  - 本番環境の環境情報を記載する
- config/deploy/staging.rb
  - ステージ環境の環境情報を記載する
- config/deploy.rb
  - 本番環境、ステージ環境共通の設定を記載する(githubのリポジトリなど)
- lib/capistrano/tasks/task.rb
  - Unicorn関連の起動、停止、再起動タスクを記載

### Capfileの編集
CapfileにはCapistrano全体の設定を記載します。
一度編集してしまえばほとんど触ることはありませんが、プラグインなどを追加する際に編集します。

```rb

require 'capistrano/setup'
require 'capistrano/deploy'
require 'capistrano/bundler'
require 'capistrano/rbenv'
require 'capistrano/rails/assets'
require 'capistrano/rails/migrations'


# taskを記述したファイルを読み込む設定
Dir.glob('lib/capistrano/tasks/*.rb').each { |r| import r }

```

行末のファイルは、最初のコマンドで作成された lib/capistrano/tasks/task.rbを指定してください。

### config/deploy/production.rb
このファイルには本番環境の環境情報を記述します。
ステージ環境、開発環境ではそれぞれ作成が必要になります。
内容は変わらないので、今回は本番環境Deployをメインに記載していきます。

```rb

# Deploy先の情報
server 'サーバのIP', user: 'サーバのユーザ', roles: %w{app db web}

# SSH設定
set :ssh_options, keys: '鍵のパス'
```
**roles**というのは、サーバの役割の名前になります。
正直、現状あまり理解できていない箇所になりますが
後述するtask.rbの中で on roles(:app)とというのがあります。
今回のdeploy先サーバは**app**とrolesを設定していますので、on roles(:app)に該当し
タスクが実行されるようになっています。

### config/deploy.rb
このファイルには、先ほど修正した環境設定ファイルに限らず共通する設定を記述します。

```rb
# capistranoのバージョン
lock '3.9.0'

# アプリケーション名
set :application, 'アプリ名'

# gitリポジトリ
set :repo_url, 'リポジトリ名'

# deployするブランチ
set :branch, 'master'

# deploy先のディレクトリ(例)。
set :deploy_to, '/var/www/rails/アプリ名'

# シンボリックリンクファイル。
set :linked_files, fetch(:linked_files, []).push('config/application.yml')

# シンボリックリンクフォルダ。
set :linked_dirs, fetch(:linked_dirs, []).push('log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'vendor/bundle', 'public/system')

# 保持するバージョン数
set :keep_releases, 5

# rubyのバージョン(例)
set :rbenv_ruby, '2.3.1'

#出力するログのレベル。
set :log_level, :debug

# コネクション継続
set :ssh_options, :keepalive => true

# Deployタスク
namespace :deploy do
  desc 'Restart application'
  task :restart do
    invoke 'unicorn:restart'
  end

  after :publishing, :restart

  after :restart, :clear_cache do
    on roles(:web), in: :groups, limit: 3, wait: 10 do
    end
  end
end
```

#### シンボリックリンクについて
Gitに関する設定がある通り、Capistranoのデプロイではgit cloneが行われます。
Figaroを利用しているため、config/application.ymlがありそこにdatabase情報などを記述しているのですが
git管理しているファイルではないため、git cloneでは利用できません。
そこで、**シンボリックリンク**という設定の箇所にconfig/application.ymlを設定することで
単純にそのファイルをサーバへ配置してくれる感じになります。

#### 保持するバージョンについて
set :keep_releases, 5　という記載について
Capstranoでデプロイすると、デプロイ先のディレクトリに
**releases**と**current**というディレクトリが作成されます。

releasesには、過去バージョンが日付ディレクトリに格納されます。その個数がkeep_releasesで設定した個数になります。
currentには、現行稼働しているバージョンが保存されます。のちのNginxではそのディレクトリをrootとします。

#### コネクション継続について
時折、デプロイに長時間かかってしまった場合、Capistranoのデプロイが強制的に終了しなんのエラーも出ずに止まる場合があります。
サーバのスペックに左右される模様なので、設定の可否はおまかせします(笑)

#### Deployタスク
Deployタスクでは、Deployの際に動作するタスクを設定できます。
現状、今記載しているものでほとんど問題はありませんが
Capfileなどでプラグインをインストールし、そのプラグイン独自のタスクが必要な場合は追加する必要があります。

### lib/capistrano/tasks/task.rb
このファイルには、後述する**Unicorn**に関するタスクを記載します。
ほとんどはコメントの通りなので、細かく修正することはないと思います。

```rb
#unicornのpidファイル、設定ファイルのディレクトリを指定
namespace :unicorn do
  task :environment do
    set :unicorn_pid,    "#{current_path}/tmp/unicorn.pid"
    set :unicorn_config, "#{current_path}/config/unicorn/production.rb"
  end

#unicornをスタートさせるメソッド
  def start_unicorn
    within current_path do
      execute :bundle, :exec, :unicorn, "-c #{fetch(:unicorn_config)} -E #{fetch(:rails_env)} -D"
    end
  end

#unicornを停止させるメソッド
  def stop_unicorn
    execute :kill, "-s QUIT $(< #{fetch(:unicorn_pid)})"
  end

#unicornを再起動するメソッド
  def reload_unicorn
    execute :kill, "-s USR2 $(< #{fetch(:unicorn_pid)})"
  end

#unicronを強制終了するメソッド
  def force_stop_unicorn
    execute :kill, "$(< #{fetch(:unicorn_pid)})"
  end

#unicornをスタートさせるtask
  desc "Start unicorn server"
  task start: :environment do
    on roles(:app) do
      start_unicorn
    end
  end

#unicornを停止させるtask
  desc "Stop unicorn server gracefully"
  task stop: :environment do
    on roles(:app) do
      stop_unicorn
    end
  end

#既にunicornが起動している場合再起動を、まだの場合起動を行うtask
  desc "Restart unicorn server gracefully"
  task restart: :environment do
    on roles(:app) do
      if test("[ -f #{fetch(:unicorn_pid)} ]")
        reload_unicorn
      else
        start_unicorn
      end
    end
  end

#unicornを強制終了させるtask
  desc "Stop unicorn server immediately"
  task force_stop: :environment do
    on roles(:app) do
      force_stop_unicorn
    end
  end
end
```

後述のUnicornはサーバにて**Worker**という形で動作します。
Nginxと同じで、起動中、停止中、再起動などのステータスがあり、Capistranoがそれを見て
起動させたり、停止させたりします。
そのタスクが記載しているメソッドになります。
上記を記述していれば、問題はないと思います。

Capistranoに関する設定は以上です。



## Unicorn設定
### 手順
- Unicornインストール
- Unicorn設定ファイル作成

### Unicornとは
Unicornは俗に言うと、アプリケーションサーバの一種です。
Unicornの中でRailsのアプリが稼働します。
ちなみに、後述するNginxはWEBサーバの一種です。
ざっくり言うと
ユーザがNginxにリクエストを送るとNginxからUnicornへ通信が走り、UnicornがRailsのアプリを返して
ブラウザで表示、みたいな感じです！

### Unicornのインストール
Gemfileに以下を追加してbundle installを行います。

```
gem 'unicorn'
```

### Unicorn設定ファイル
Capistranoの設定ファイルで記述したように、設定ファイルは以下に作成します。

```bash
touch /config/unicorn/production.rb
```

Unicornに関する設定ファイルは一つだけです。

```rb

#ワーカーの数
  $worker  = 2
#ワーカーの削除時間
  $timeout = 30
#自分のアプリケーションディレクトリ(例)
  $app_dir = "/var/www/rails/アプリ名/current"
#sockのディレクトリ
  $listen  = File.expand_path 'tmp/unicorn.sock', $app_dir
#PIDのディレクトリ
  $pid     = File.expand_path 'tmp/unicorn.pid', $app_dir
#エラーログ
  $std_log = File.expand_path 'log/unicorn.log', $app_dir

  worker_processes  $worker
  working_directory $app_dir
  stderr_path $std_log
  stdout_path $std_log
  timeout $timeout
  listen  $listen
  pid $pid

#fork前
  before_fork do |server, worker|
    defined?(ActiveRecord::Base) and ActiveRecord::Base.connection.disconnect!
    old_pid = "#{server.config[:pid]}.oldbin"
    if old_pid != server.pid
      begin
        Process.kill "QUIT", File.read(old_pid).to_i
      rescue Errno::ENOENT, Errno::ESRCH
      end
    end
  end

#fork後
  after_fork do |server, worker|
    defined?(ActiveRecord::Base) and ActiveRecord::Base.establish_connection
  end
```
ワーカーは先ほど説明した、Unicornの本体になります。
アプリケーションディレクトリは、Capistranoが作成するcurrentを指定してください。
基本設定ファイルでディレクトリ変更以外、触ることはありません。

以上で、ローカルでの対応は終了になります。
次以降はサーバ上での作業になります
一旦長くなってきたので、キリがいいところで止めて、②で続きを記述します。

次回: [Rails5.1.2 + Webpacker + ReactをCapstranoでデプロイする手順書②](http://qiita.com/gcmae/items/9f4aa882ada24aa39066)