デプロイを自動化する

##はじめに
「AWSのサーバーを利用する」ための手順を5つに分けて書いています。

記事は以下にまとめておりますのでご確認ください。

①[EC2の初期設定](https://qiita.com/maca12vel/items/902dde37a267ceca1c53)
②[本番環境でデータベースを作成する](https://qiita.com/maca12vel/items/68d6ae3d4308e330847d) 
③[EC2のRailsを起動する](https://qiita.com/maca12vel/items/2a04d39f958b53d687e2)
④[Webサーバーを設定する](https://qiita.com/maca12vel/items/35f9fb73bb21cb4869fb) 
⑤[デプロイを自動化する](https://qiita.com/maca12vel/items/7b33dd6ea1ad556e3fec) ← イマココ

##デプロイの自動化
手動で行っていたデプロイ作業（「unicorn_railsコマンド」を使ってサーバーを立ち上げる手段）を、
ローカルのターミナルからのコマンド1つで行えるようにする。
そのために、「自動デプロイツール」と呼ばれるものを利用する。

今回はCapistranoという自動デプロイツールを導入する。

##導入準備
Capistranoを利用するためのGemをGemfileにインストール
その後、アプリケーションディレクトリでbundle install

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

gemを読み込めたら、下記のコマンドを入力

ターミナル（ローカル）
※アプリケーションディレクトリ

```
% bundle exec cap install
```

下記のようにファイルが生成される
[![Image from Gyazo](https://i.gyazo.com/25114e289e99ab4efe21175535148ac8.png)](https://gyazo.com/25114e289e99ab4efe21175535148ac8)

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

###production.rbを編集

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

###deploy.rbを編集
deploy.rbの記述をすべて削除し、以下のコードを貼り付ける
注意箇所は
「Capistranoのバージョン」 → Gemfile.lockに記載されている
「アプリケーション名」
「GitHubのユーザー名 , レポジトリ名」
「このアプリで使用しているrubyのバージョン」
「自身のキーペア名」


```config/deploy.rb
# 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による自動デプロイを実行すると本番環境のアプリケーションのディレクトリが変化する。
Capistranoによるアプリのバックアップなど、複数のディレクトリが作成される。

**下記の3つは特に重要**

####``releasesディレクトリ``
「releasesディレクトリ」には、Capistranoを通じてデプロイされたアプリがひとまとめにされる。
ここに過去分のアプリが残っていることにより、デプロイ時に何か問題が発生しても前のバージョンに戻れる。
過去分の保存数を指定しているのがdeploy.rbの「set :keep_releases」の記述。
今回は5つ、過去のバージョンを保存するよう設定。

####``currentディレクトリ``
「currentディレクトリ」には、releasesフォルダの中で一番新しいものが
自動的にコピーされているような状態になっている。
つまり、「現在デプロイされている内容＝current内の内容」ということになる。

####``sharedディレクトリ``
バージョンが変わっても共通で参照されるディレクトリが格納されるディレクトリ。
具体的には、log、public、tmp、vendorディレクトリが格納される。

##Unicornの設定ファイルを編集
手動デプロイの時と比べ、自動デプロイ時にはRailsのアプリケーションのディレクトリが
1段階深くなっている。そのため、数ヶ所変更を加える必要がある。

```【編集前】config/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

# 「current」を指定
working_directory "#{app_path}/current"

# 「shared」の中を参照するよう変更
listen "#{app_path}/shared/tmp/sockets/unicorn.sock"

# 「shared」の中を参照するよう変更
pid "#{app_path}/shared/tmp/pids/unicorn.pid"

# 「shared」の中を参照するよう変更
stderr_path "#{app_path}/shared/log/unicorn.stderr.log"

# 「shared」の中を参照するよう変更
stdout_path "#{app_path}/shared/log/unicorn.stdout.log"
（省略）
```

##Nginxの設定ファイルを編集
Unicornの設定ファイルと同様、手動デプロイの時と比べ、
自動デプロイ時にはRailsのアプリケーションのディレクトリが1段階深くなっている。
そのため、数ヶ所変更を加える必要がある。

ターミナル(EC2内)で実行

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

以下を編集
①3行目：「〜アプリケーション名/shared/tmp/〜」に編集
②14行目：1行丸ごと追加　→　root /var/www/アプリケーション名/current/public;
③20行目：1行丸ごと追加　→　root /var/www/アプリケーション名/current/public;

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

入力を終えたら「escキー」→「:wq」の順で実行し、保存する。
Nginxの設定を変更したら、忘れずに再読込・再起動

ターミナル(EC2内)で実行

```
[ec2-user@ip-***-**-**-*** ~]$ sudo systemctl reload nginx
[ec2-user@ip-***-**-**-*** ~]$ sudo systemctl restart nginx
```

##データベースの起動を確認
データベースが立ち上がっていないとデプロイが失敗するので、以下のコマンドでデータベースの状態を確認する。

ターミナル(EC2内)で実行

```
[ec2-user@ip-***-**-**-*** ~]$ sudo systemctl status mariadb 
```

以下のように、「active」と表示されれば起動している。

```
● mariadb.service - MariaDB database server
   Loaded: loaded (/usr/lib/systemd/system/mariadb.service; disabled; vendor preset: disabled)
   Active: active (running) since 金 2020-07-17 03:46:51 UTC; 8s ago
  Process: 17044 ExecStartPost=/usr/libexec/mariadb-wait-ready $MAINPID (code=exited, status=0/SUCCESS)
  Process: 17008 ExecStartPre=/usr/libexec/mariadb-prepare-db-dir %n (code=exited, status=0/SUCCESS)
 Main PID: 17043 (mysqld_safe)
   CGroup: /system.slice/mariadb.service
           ├─17043 /bin/sh /usr/bin/mysqld_safe --basedir=/usr
           └─17206 /usr/libexec/mysqld --basedir=/usr --datadir=/var/lib/mysql --plugin-dir=/usr/lib64/mysql/plugin --log-error=/var/log/mariadb/mariadb.log --pid-file=/var/run/mariadb/mariadb.pid --so...
```

※「active」になっていない場合はsudo systemctl start mariadbを実行

##Unicornのプロセスをkill
自動デプロイをする前に、unicornのプロセスをkillする必要がある。
すでにunicornのサーバーが立ち上がっている状態で自動デプロイをすると、
二重でサーバーを立ち上げることになるため。
（自動デプロイもサーバーを立ち上げる役割を担っている）

①プロセスを確認

```
[ec2-user@ip-***-**-**-*** <リポジトリ名>]$ ps aux | grep unicorn

ec2-user 17877  0.4 18.1 588472 182840 ?       Sl   01:55   0:02 unicorn_rails master -c config/unicorn.rb -E production -D
ec2-user 17881  0.0 17.3 589088 175164 ?       Sl   01:55   0:00 unicorn_rails worker[0] -c config/unicorn.rb -E production -D
ec2-user 17911  0.0  0.2 110532  2180 pts/0    S+   02:05   0:00 grep --color=auto unicorn
```

②プロセスをkill

```
# 上記の例だと「7877」
[ec2-user@ip-***-**-**-*** <リポジトリ名>]$ kill プロセス番号
```

###ローカルでの修正をすべてmasterにpush
ローカルでのコードの変更が、すべてmasterにpushされていることを確認しておく。
以上で自動デプロイの準備は完了。

##自動デプロイを実行
ローカルのターミナルに戻り、以下のコマンドで自動デプロイを実行

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

※ EC2インスタンスの再起動後は、必ず「データベース」「Nginx」の再起動も行う

ターミナル(EC2内)で実行

```
[ec2-user@ip-***-**-**-*** ~]$ sudo systemctl restart mariadb 
[ec2-user@ip-***-**-**-*** ~]$ sudo systemctl restart nginx
```

##ブラウザで確認
ブラウザからElastic IPでアクセスする。
※ 「http://＜Elastic IP＞:3000/」ではなく「http://＜Elastic IP＞/」なので注意。

---

以上です。お疲れ様でした。