AWS デプロイを自動化する

# はじめに
今回、オリアプを制作し、その際にEC2でデプロイし、ローカル環境から本番環境に自動でデプロイする設定をしましたので、備忘録としてつけたいと思います！

# 使用Gem
Capistrano
※自動デプロイツールです。

# 自動デプロイツールのメリット
このようなツールを使うことでデプロイ時のコマンドを１つでできちゃうことが最大のメリットです！
多くのコマンドを打つことによって、打ち間違えを防ぐことができます。


# Capistranoを利用するための準備

```
Gemfile
group :development, :test do
  gem 'capistrano'
  gem 'capistrano-rbenv'
  gem 'capistrano-bundler'
  gem 'capistrano-rails'
  gem 'capistrano3-unicorn'
end

# group :developmentのグループがない場合は追加してください。

% bundle install

% bundle exec cap install
#アプリケーションのディレクトリで実行することにより、必要ファイルの生成がされます。

```

## Capfile
このファイルは、「Capistrano」の関連ライブラリのうちのどれを読み込むかを指定できます。
「Capistrano」は、いくつかのライブラリに分かれているため、そのいくつかよ読み込む必要があります。

## production.rb
デプロイについて設定を書くファイルです。
GitHubへの接続に必要なsshキーの指定、デプロイ先のサーバのドメイン、AWSサーバへのログインユーザー名、サーバにログインしてからデプロイのために何をするか、といった設定を記載します。
また、「deploy.rb」「staging.rb」も同様の役割をするファイルです。


# Capfileを編集します。

```
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 }

```
requireによって引数として置かれた文字列が指すディレクトリが読み込まれて、その中にデプロイに際して必要な動作を一通り記述しています。

# デプロイについての設定ファイルを編集します。

```
config/deploy/production.rb
# 一番下に下記を記述します。
server '用意したElastic IP', user: 'ec2-user', roles: %w{app db web}
```


```
config/deploy

#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のバージョン' #カリキュラム通りに進めた場合、’2.6.5’ です

# どの公開鍵を利用してデプロイするか
set :ssh_options, auth_methods: ['publickey'],
                                  keys: ['~/.ssh/ご自身のキーペア名.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のバージョン」は、Gemfile.lockに記載されているのでご確認ください！


# Unicornの設定ファイルを編集します。

手動デプロイの時と、自動デプロイ時にはRailsのアプリケーションのディレクトリが１段回深くなっています。
そのため「Unicorn.rb」の設定を編集します。

【編集前】

```
#サーバ上でのアプリケーションコードが設置されているディレクトリを変数に入れておく
app_path = File.expand_path('../../', __FILE__)

#アプリケーションサーバの性能を決定する
worker_processes 1

#アプリケーションの設置されているディレクトリを指定
working_directory app_path

#Unicornの起動に必要なファイルの設置場所を指定
pid "#{app_path}/tmp/pids/unicorn.pid"

#ポート番号を指定
listen 3000

#エラーのログを記録するファイルを指定
stderr_path "#{app_path}/log/unicorn.stderr.log"

#通常のログを記録するファイルを指定
stdout_path "#{app_path}/log/unicorn.stdout.log"

（省略）
```

【編集後】

```
config/unicorn.rb

#サーバ上でのアプリケーションコードが設置されているディレクトリを変数に入れておく
app_path = File.expand_path('../../../', __FILE__)  # 「../」が一つ増えている

#アプリケーションサーバの性能を決定する
worker_processes 1

#アプリケーションの設置されているディレクトリを指定
working_directory "#{app_path}/current"  # 「current」を指定

#Unicornの起動に必要なファイルの設置場所を指定
pid "#{app_path}/shared/tmp/pids/unicorn.pid"  # 「shared」の中を参照するよう変更

#ポート番号を指定
listen "#{app_path}/shared/tmp/sockets/unicorn.sock"  # 「shared」の中を参照するよう変更

#エラーのログを記録するファイルを指定
stderr_path "#{app_path}/shared/log/unicorn.stderr.log"  # 「shared」の中を参照するよう変更

#通常のログを記録するファイルを指定
stdout_path "#{app_path}/shared/log/unicorn.stdout.log"  # 「shared」の中を参照するよう変更
（省略）

```

# Nginxの設定ファイルを編集します。
ここも同じく、手動デプロイ時より、自動デプロイ時の方がディレクトリが1段階深くなっているので変更を加えます。

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

```
/etc/nginx/conf.d/rails.conf

upstream app_server {
  # Unicornと連携させるための設定
  server unix:/var/www/アプリケーション名/shared/tmp/sockets/unicorn.sock;
}

# {}で囲った部分をブロックと呼ぶ。サーバの設定ができる
server {
  # このプログラムが接続を受け付けるポート番号
  listen 80;
  # 接続を受け付けるリクエストURL ここに書いていないURLではアクセスできない
  server_name Elastic IP;

  # クライアントからアップロードされてくるファイルの容量の上限を2ギガに設定。デフォルトは1メガなので大きめにしておく
  client_max_body_size 2g;

# 接続が来た際のrootディレクトリ
  root /var/www/アプリケーション名/current/public;

# assetsファイル(CSSやJavaScriptのファイルなど)にアクセスが来た際に適用される設定
  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の設定を変更したら、再読み込み、再起動を行います！
また、DBの起動も確認しておきます。
DBが立ち上がっていないとデプロイが失敗します！

```
[ec2-user@ip-ご自身のIP ~]$ sudo systemctl reload nginx
[ec2-user@ip-ご自身のIP ~]$ sudo systemctl restart nginx

[ec2-user@ip-ご自身のIP ~]$ sudo systemctl status mariadb 
 # DBの起動確認！もし起動していなければsudo systemctl start mariadb
```

## Unicornのプロセスをkillします。
自動デプロイをする前に、プロセスをkillする必要があります。
理由は、現在立ちがっているものと二重にサーバーを立ち上げることになるからです。

```
[ec2-user@ip-ご自身のIP <リポジトリ名>]$ ps aux | grep unicorn
#立ち上がっているunicorn_rails masterのプロセスidを確認する

[ec2-user@ip-ご自身のIP <リポジトリ名>]$ kill プロセス番号
```

ローカルリポジトリにローカルでの修正箇所が残っていれば「master」にpush
しておきましょう！
※自動デプロイはGitHubのリモートリポジトリに反映される訳ではないためです。


# 自動デプロイをします。

ご自身のローカルのアプリケーションのターミナルから

```
# アプリケーションのディレクトリで実行しましょう
% bundle exec cap production deploy

```
エラーがでなければすごい勢いで表示がでてきます。

# 最後に

自動デプロイかなり便利です！設定の手順が多く煩わしく感じるかと思うかもしれませんが、一度設定してしまえば今後は楽です。

実際使ってみてherokuの時だと色々コマンドが必要でしたけど、１つのコマンドで上げれるなんて感激です。

ここまで読んでいただきありがとうございました！