AWS:capistranoデプロイ方法

AWSに再デプロイするのは大変な作業で、変更内容が反映されないというエラーも起きやすいので、コマンド1つでデプロイ出来る方法は無いか探しました。

#これまでのデプロイ
1. git push
2. git pull
3. SSH接続
4. アセットコンパイル
5. Unicorn再起動

とても面倒ですよね・・・

Capistrano を使い，1コマンドで Rails アプリを AWS EC2 にデプロイできる状態にしようと思いました。
capistranoを利用することでサーバーにログインしなくてもコマンド一つで再デプロイ可能な為、非常に楽です。
一度Capistranoにデプロイが成功すれば、簡略してエラーなしにデプロイができます。

#Capistranoの導入

```
Gemfile

group :development do
  # 略
  # ***** 以下を追加 *****
  gem "capistrano", "~> 3.10", require: false
  gem "capistrano-rails", "~> 1.6", require: false
  gem 'capistrano-rbenv', '~> 2.2'
  gem 'capistrano-rbenv-vars', '~> 0.1'
  gem 'capistrano3-puma'
  # ***** 以上を追加 *****
end
```

```
ローカル環境のターミナル

bundle install
bundle exec cap install STAGES=production
```

```
Capfile の # require "capistrano/passenger" の下に以下を追加


Capfile

require 'capistrano/rbenv'
require 'capistrano/bundler'
require 'capistrano/rails/assets'
require 'capistrano/rails/migrations'
require 'capistrano/puma'
install_plugin Capistrano::Puma
install_plugin Capistrano::Puma::Systemd
install_plugin Capistrano::Puma::Nginx
```

```
デプロイの設定ファイルを修正・追記しましょう。
「アプリ名」「GitHubリポジトリURL」は各自のものに置き換えて下さい。
「GitHubリポジトリURL」は HTTPS でなく SSH のURLをコピペして下さい。

config/deploy.rb

# config valid for current version and patch releases of Capistrano
lock "~> 3.14.1"

# ***** 以下を修正 *****
set :application, "アプリ名"
set :repo_url, "GitHubのリポジトリURL"
set :rbenv_ruby, File.read('.ruby-version').strip
set :branch, ENV['BRANCH'] || "master"

# Nginxの設定ファイル名と置き場所を修正
set :nginx_config_name, "#{fetch(:application)}.conf"
set :nginx_sites_enabled_path, "/etc/nginx/conf.d"

append :linked_files, "config/master.key"
append :linked_dirs, "log", "tmp/pids", "tmp/cache", "tmp/sockets", "node_modules"
# ***** 以上を追加 *****
```

```
production.rb の一番上に，EC2サーバーにログインするユーザー名、サーバーのロールを記述して下さい。
「ElatsticIP」「アプリ名」「ユーザー名」は各自のものに置き換えて下さい。

config/deploy/production.rb

server "ElatsticIP", user: "ユーザー名", roles: %w{app db web}

set :ssh_options, {
  keys: %w(~/.ssh/アプリ名.pem),
  forward_agent: true,
  auth_methods: %w(publickey),
}
```

##master.key の配置と Rails アプリのデプロイ


準備が整いましたので，Railsアプリのデプロイを行います。

初回の実行では master.key がないためデプロイに失敗しますが， master.key を配置するために必要なディレクトリが生成されます。

デプロイ失敗後に scp コマンドで master.key をサーバー側に追加し，再度実行すればデプロイに成功します。


```
ローカル環境のターミナル

# Railsアプリのルートディレクトリに移動してから
bundle exec cap production deploy

# 「ERROR linked file /var/www/アプリ名/shared/config/master.key does not exist on ElasticIP」が出ればOK

scp config/master.key $APP_NAME:/var/www/$APP_NAME/shared/config
bundle exec cap production puma:config
bundle exec cap production puma:systemd:config puma:systemd:enable
```

【注意】 ブランチが master でない場合は， BRANCH=HEAD を付けた bundle exec cap production deploy BRANCH=HEAD を実行して下さい.

最後のコマンドで， /etc/systemd/system/puma_アプリ名_production.service が作成されます。このファイルの $HOME を実際のパスに変更しないとエラーが出るため，修正して下さい。

```
サーバー環境のターミナル

echo $HOME

# ここで表示されるパス「/home/ユーザー名」をコピー

cd /etc/systemd/system/
vi puma_${APP_NAME}_production.service

# 開かれたファイルの ExecStart=$HOME の $HOME を先ほどコピーしたものに置き換えて保存終了です！

sudo systemctl daemon-reload
sudo systemctl enable puma_${APP_NAME}_production.service
```

これで準備が完了です。再度デプロイしてみます！

```
ローカル環境のターミナル

bundle exec cap production deploy
```

【備考】ここでデプロイに失敗した場合は，まずエラー文を確認します。いろいろなケースがありますが，アプリで使用されている gem 次第では，先に依存関係にあるプラグインを EC2 にインストールしておく必要があります。


##Nginx の設定

Nginx 用の設定ファイルを追加するため，先に必要なディレクトリをサーバー側で作成しておきます。

```
サーバー環境のターミナル

cd /etc/nginx
sudo mkdir sites-available}
```

ローカル環境 のターミナルで，Railsアプリのルートディレクトリまで移動した後，以下を実行します。
これで Nginx 用の設定が生成されます。

```
ローカル環境のターミナル

# Railsアプリのルートディレクトリに移動してから
bundle exec cap production puma:nginx_config
```

これで，サーバー側の /etc/nginx/conf.d に設定ファイル アプリ名.conf が入ります。

Nginx を再起動します。

```
サーバー環境のターミナル(/etc/nginx)

sudo service nginx restart
```

ブラウザのアドレスバーに Elastic IP を入力してアクセスし， スーパーリロード して下さい。（ショートカットキーは command + shift + r）

アプリが表示されればOKです。

【補足】アプリが表示されない場合は，以下↓を試して下さい.

ローカル環境のターミナルから curl -I ElasticIP を実行したとき，最初に HTTP/1.1 301 Moved Permanently が出力される場合
config/environments/production.rb の config.force_ssl = true をコメントアウトして下さい。