Capistranoを用いた自動デプロイ

## Capistranoとは
自動でデプロイが行えるツールです。
Capistranoを使うことで、以下の2つの記事で行ったデプロイ作業が自動化できます。
<a href="https://qiita.com/ysda/items/359ba0afa23741db192b">AWSへのRailsアプリのデプロイ その1
</a><a href="https://qiita.com/ysda/items/246009da5aea8cc29666">AWSへのRailsアプリのデプロイ その2
</a>

## gemのインストール
まずは必要なgemのインストールから行います。

```
group :development, :test do
  gem 'capistrano'
  gem 'capistrano-rbenv'
  gem 'capistrano-bundler'
  gem 'capistrano-rails'
  gem 'capistrano3-unicorn'
end
```
```
bundle install
```
gemをインストールしたら、以下のコマンドを実行します。

```
bundle exec cap install
```
これで以下のファイルが作成されますので、確認しておきましょう。
Capfile
deploy.rb
production.rb
staging.rb

## 設定ファイルの編集

・Capfile
CapfileでCapistrano関連のライブラリのうちどれを読み込むかを指定できます。

```
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
このファイルにEC2インスタンスのIPを記述しましょう。

```
server 'ElasticIP', user: 'ec2-user', roles: %w{app db web}
```
・deploy.rb
このファイルにはバージョンやリポジトリの情報を記述します。
下記のフォーマットに沿って各項目を埋めましょう。

```
lock 'Capistranoのバージョン'

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

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: ['EC2インスタンスのSSH鍵へのパス'] 

set :unicorn_pid, -> { "#{shared_path}/tmp/pids/unicorn.pid" }

set :unicorn_config_path, -> { "#{current_path}/config/unicorn.rb" }
set :keep_releases, 5

after 'deploy:publishing', 'deploy:restart'
namespace :deploy do
  task :restart do
    invoke 'unicorn:restart'
  end
end
```
・unicorn.rb
Capistranoでのデプロイ後はアプリケーションのディレクトリ直下に存在するcurrentディレクトリが参照されます。そのため、working_directoryやpidのパスを変更します。

```
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の設定
capistranoを使用するためにいろいろな設定ファイルに変更を加えてきました。
それに伴い、nginxの設定にも色々と修正を加える必要があります。
EC2インスタンス上でvimを使ってrails.confを編集しましょう。

```
sudo vim /etc/nginx/conf.d/rails.conf
```
rails.confを以下のように書き換えます。
アプリケーション名やElasticIPは適宜読み替えてください。

```
upstream app_server {
  server unix:/var/www/アプリケーション名/shared/tmp/sockets/unicorn.sock;
}

server {
  listen 80;
  server_name 'Elastic IP';

  client_max_body_size 2g;

  root /var/www/アプリケーション名/current/public;

  location ^~ /assets/ {
    gzip_static on;
    expires max;
    add_header Cache-Control public;
    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、mysql、unicornの再起動を行い、ローカルでの修正をリモートリポジトリに反映すれば準備完了です。

```
sudo service nginx reload
sudo service nginx restart
sudo service mysqld restart
ps aux | grep unicorn #unicornのプロセスIDを確認
kill xxxx #unicornのプロセスをkillする
```
ローカルで下記のコマンドを実行し、自動デプロイしてみましょう。

```
bundle exec cap production deploy
```

これでデプロイ出来ているはずです。

## エラーが出たら
デプロイ中のエラーメッセージや、下記のエラーログを確認してみましょう。
/var/www/リポジトリ名/current/log/unicorn.stderr.log
/var/log/nginx/error.log

また、EC2インスタンスの再起動も有効です。

```
shutdown -r now
```