【　Ruby on Rails 6.0　】AWS + Nginx + Unicornでデプロイ④

# 始めに
前回の記事ではEC２インスタンスにmariaDBというデータベースの設定を行いました。今回はインスタンス上でRailsアプリの起動に必要なGemをインストールし環境変数を設定する工程までをまとめたいと思います。

# 目次
|目次|内容|
|:--:|:--:|
|セクション1|[EC2インスタンス作成](https://qiita.com/anago1030/items/854252bc9b728fe90beb)|
|セクション2|[Linuxサーバー構築](https://qiita.com/anago1030/items/07f7026c0f4c42a63440)|
|セクション3|[データベース設定](https://qiita.com/anago1030/items/79eebdc8474255b962b4)|
|セクション4|**EC2上でGemをインストールし環境変数を設定**(今回の内容)|
|セクション5|[Railsアプリを起動](https://qiita.com/anago1030/items/36d0da7e25c57d0e5780)|
|セクション6|[Nginxの導入](https://qiita.com/anago1030/items/c4c80a46a75ff306db8d)|
|セクション7|[自動デプロイ](https://qiita.com/anago1030/items/cb60c8e99d408dc4fd80)|
|セクション8|[独自ドメイン取得](https://qiita.com/anago1030/items/5e487ec48fd7c0be86bc)|

## EC2のサーバにアプリのコードをクローン
全世界に公開できるIPアドレスを持ったEC2サーバ上でRailsアプリを動かすためにアプリケーションのコードをGithubからEC2サーバへクローンします。

### GithubにSSH鍵を登録
現状、EC2サーバにアプリケーションのコードをクローンしようとしても permission deniedとエラーが出てしまいます。これは、Githubから見てこのEC2インスタンスが何者かわからないためです。

EC2インスタンスからGithubにアクセスするためには、作成したEC2インスタンスのSSH 公開鍵をGithubに登録する必要があります。 SSH鍵をGithubに登録すると、Githubはそれを認証に利用し、コードのクローンを許可してくれるようになります。

```php:ターミナル
[ec2-user@ip-172-31-23-189 ~]$ ssh-keygen -t rsa -b 4096

# 三段階ほど認証を求められるが全てyesでenterを押す

Enter file in which to save the key (/home/ec2-user/.ssh/id_rsa):
Enter passphrase (empty for no passphrase): 
Enter same passphrase again:

# 以下の表示が出れば成功

Your identification has been saved in /home/ec2-user/.ssh/id_rsa.
Your public key has been saved in /home/ec2-user/.ssh/id_rsa.pub.
The key fingerprint is:
3a:8c:1d:d1:a9:22:c7:6e:6b:43:22:31:0f:ca:63:fa ec2-user@ip-172-31-23-189
The key's randomart image is:
+--[ RSA 4096]----+
|    +            |
| . . =           |
|  = . o .        |
| * o . o         |
|= *     S        |
|.* +     .       |
|  * +            |
| .E+ .           |
| .o              |
+-----------------+

# .SSH公開鍵を表示し、値をコピーするため、下記コマンドを実装
[ec2-user@ip-172-31-23-189 ~]$ cat ~/.ssh/id_rsa.pub

# ssh~から最後の文字列までをコピーする
ssh-rsa AAAAB3Nza・・・・・
```
以下のURLからGithubにアクセスします。
[https://github.com/settings/keys](https://github.com/settings/keys)
アクセスしたら以下の画像のように操作します。
![スクリーンショット 2021-02-25 4.06.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/772095/25f448da-c012-66e8-1e36-6a30f0ec8494.png)

![スクリーンショット 2021-02-25 4.12.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/772095/fc0cf441-e468-9ade-d8e7-7ccb8c0fbd6a.png)
Githubに鍵を登録できたら、SSH接続できるか以下のコマンドで確認してみましょう。

```php:ターミナル
[ec2-user@ip-172-31-23-189 ~]$ ssh -T git@github.com

# 下記の表示が出たらyesを選択

The authenticity of host 'github.com (IP ADDRESS)' can't be established.
RSA key fingerprint is 16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48.
Are you sure you want to continue connecting (yes/no)?

# 成功したら下記の表示が出る

[ec2-user@ip-172-31-23-189 ~]$ ssh -T git@github.com
Hi <Githubユーザー名>! You've successfully authenticated, but GitHub does not provide shell access.

# エラーが出たらログインし直してもう一度ssh接続する

Warning: Permanently added the RSA host key for IP address 'XXXXXXXXX' to the list of known hosts.
```

## アプリケーションサーバの設定
アプリケーションサーバとは、ブラウザからの「リクエスト」を受け付けRailsアプリケ ーションを実際に動作させるソフトウェアのことです。
アプリケーションサーバが動いていれば、ブラウザからのリクエストを受け付けてRails アプリケーションが動作します。
という訳で、全世界に公開するEC2サーバ上でもアプリケーションサーバを動かす必要が あるのです。今回は`Unicorn`というアプリケーションサーバーを使用します。

### Unicorn
全世界に公開されるサーバ上で良く利用されるアプリケーションサーバです。rails sコマンドの代わりに unicorn_rails コマンドで起動することができます。
この後、EC2サーバにSSH接続しUnicornを起動することで全世界からアクセスできるようにしていきます。

### Unicornをインストール
UnicornはRubyで作成されており、gem化されています。なのでローカルのGemfileを編集しましょう。

```php:Gemfile
# 追記（本番環境）
group :production do
  gem 'unicorn', '5.4.1' # バージョン指定
end
```

```php:ターミナル（ローカル）
$ bundle install
```

### config/unicorn.rbを作成し、内容を以下のように編集
Unicornの設定ファイルとして、次の内容でファイルを作成しましょう。最初からは存在していないので、自分でconfig ディレクトリ以下に作成します。
この後すぐ、ファイルの中身がそれぞれ何を行なっているか説明しますので、まずはコピ ー&ペーストで作成したファイルに貼り付けましょう。

```php: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"

#Railsアプリケーションの応答を待つ上限時間を設定
timeout 60

#以下は応用的な設定なので説明は割愛

preload_app true
GC.respond_to?(:copy_on_write_friendly=) && GC.copy_on_write_friendly = true

check_client_connection false

run_once = true

before_fork do |server, worker|
  defined?(ActiveRecord::Base) &&
    ActiveRecord::Base.connection.disconnect!

  if run_once
    run_once = false # prevent from firing again
  end

  old_pid = "#{server.config[:pid]}.oldbin"
  if File.exist?(old_pid) && server.pid != old_pid
    begin
      sig = (worker.nr + 1) >= server.worker_processes ? :QUIT : :TTOU
      Process.kill(sig, File.read(old_pid).to_i)
    rescue Errno::ENOENT, Errno::ESRCH => e
      logger.error e
    end
  end
end

after_fork do |_server, _worker|
  defined?(ActiveRecord::Base) && ActiveRecord::Base.establish_connection
end
```

### 変更修正をリモートリポジトリに反映
ここまで、ローカルのフォルダ内で変更修正を行ったので、こちらをリモートリポジトリへ反映します。変更修正をコミットしてプッシュしましょう。
この時必ず、`masterブランチ`で行うようにしてください。もし、別ブランチでコミット&プッシュした場合は、リモートリポジトリでプルリクエストを作成し、ブランチをmasterへマージしてください。

## Githubからコードをクローン
続いて、Unicornの設定を済ませたコードをEC2インスタンスにクローンします。

### /var/wwwディレクトリを作成し、権限をec2-userに変更

```php:ターミナル（EC2）
#/var/wwwディレクトリを作成(後述するCapistranoの初期値がwwwなので、ディレクトリをwwwに設定しています）
[ec2-user@ip-172-31-23-189 ~]$ sudo mkdir /var/www/

#作成したwwwディレクトリの権限をec2-userに変更
[ec2-user@ip-172-31-23-189 ~]$ sudo chown ec2-user /var/www/
```

### Githubから「リポジトリURL」を取得
![スクリーンショット 2021-02-25 4.29.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/772095/4e2a3049-301a-96e2-71fc-8f708429701f.png)
取得した「リポジトリURL」を使って、コードをクローンします。

```php:ターミナル(EC2)
[ec2-user@ip-172-31-23-189 ~]$ cd /var/www/
[ec2-user@ip-172-31-23-189 www]$ git clone https://github.com/リポジトリURL

# 成功したら以下の表示が出る

remote: Enumerating objects: 298, done.
remote: Counting objects: 100% (298/298), done.
remote: Compressing objects: 100% (190/190), done.
remote: Total 298 (delta 109), reused 274 (delta 86), pack-reused 0
Receiving objects: 100% (298/298), 58.53 KiB | 365.00 KiB/s, done.
Resolving deltas: 100% (109/109), done.
```

### EC2の能力を拡張
現状動かしているEC2のインスタンスではコンピューターの能力が足りず、Gemのインストール時などにエラーが発生する可能性があります。具体的には、コンピューターの処理能力に関係するメモリというものが足りません。これは、無料で動かせるインスタンスの限界であるため仕方ありません。
そこで、今後の設定を行う前にメモリを増強する処理を行います。

```php:ターミナル
# ホームディレクトリに移行
[ec2-user@ip-172-31-25-189 ~]$ cd ~
[ec2-user@ip-172-31-25-189 ~]$ sudo dd if=/dev/zero of=/swapfile1 bs=1M count=512

# 成功すると以下の表示が出る

512+0 レコード入力
512+0 レコード出力
536870912 バイト (537 MB) コピーされました、 5.19011 秒、 103 MB/秒

# 次は権限に制限をかけましょう（chmodコマンド）
[ec2-user@ip-172-31-25-189 ~]$ sudo chmod 600 /swapfile1

# スワップ（swap）領域を作成する　－　mkswap
[ec2-user@ip-172-31-25-189 ~]$ sudo mkswap /swapfile1

#成功すると下記の表示が出ます
スワップ空間バージョン1を設定します、サイズ = 524284 KiB
ラベルはありません, UUID=74a961ba-7a33-4c18-b1cd-9779bcda8ab1

# スワップ（swap）領域を有効化する　－　swapon
[ec2-user@ip-172-31-25-189 ~]$ sudo swapon /swapfile1
[ec2-user@ip-172-31-25-189 ~]$ sudo sh -c 'echo "/swapfile1  none        swap    sw              0   0" >> /etc/fstab'
```

### gemをインストール

```php:ターミナル(EC2)
# まずは、EC２にダウンロードしたWEB Appを開く
[ec2-user@ip-172-31-23-189 www]$ cd  /var/www/アプリ名

# Rubyのバージョンを確認する
[ec2-user@ip-172-31-23-189 <アプリ名>]$ ruby -v

# 指定したrubyのバージョンが表示されれば成功です。
ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-linux]
```

### 本番環境でgemを管理するための bundlerをインストール
まず開発環境(ローカル)で開発してきたアプリにおいて、どのバージョンの bundlerが使われていたのか確認します。

```php:ターミナル（ローカル）
$ bundler -v

# するとバージョンが表示されます
Bundler version 2.1.4 # 人によってバージョンが違う可能性があります
```
開発環境で仕様しているbundlerのバージョンがわかったので、同じバージョンのものを EC2サーバ側にも導入します。上記の場合では、bundler 2.1.4のバージョンを導入して`bundle install`を実行します。

```php:ターミナル（EC2）
# ローカルで確認したbundlerのバージョンを導入する
[ec2-user@ip-172-31-23-189 <アプリ名>]$ gem install bundler -v 2.1.4
Fetching bundler-2.1.4.gem
Successfully installed bundler-2.1.4
Parsing documentation for bundler-2.1.4
Installing ri documentation for bundler-2.1.4
Done installing documentation for bundler after 3 seconds
1 gem installed

# 上記コマンドは、数分以上かかる場合もあります。
[ec2-user@ip-172-31-23-189 <アプリ名>]$ bundle install
```

## 環境変数の設定
データベースのパスワードなどセキュリティのためにGithubにアップロードすることがで きない情報は、環境変数というものを利用して設定します。
環境変数は、Railsからは ENV['<環境変数名>'] という記述でその値を利用することができます。今回は、SECRET_KEY_BASE という環境変数を指定していきます。

### secret_key_baseを作成

```php:ターミナル(EC2)
[ec2-user@ip-172-31-23-189 <アプリ名>]$ rake secret

# うまくいくと、
cdfasdfadgfsadfdgc314751a8dadfadf7c8b9a1dc888e...
という感じで表示されます。
これをコピーしておきましょう
```
環境変数は /etc/environment というファイルに保存することで、サーバ全体に適用さ れます。環境変数の書き込みはvimコマンドを使用して行います。

```php:ターミナル
[ec2-user@ip-172-31-23-189 <アプリ名>]$ sudo vim /etc/environment
```
![スクリーンショット 2021-02-25 4.43.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/772095/4b457349-4173-415e-dd7d-57b413840795.png)
上の様な画面になれば、iと打ち込んで入力モードに切り替えた後、下記の記述を打ち込みます。 `=` の前後にスペースは入れません。

```php:/etc/environment
DATABASE_PASSWORD='データベースのrootユーザーのパスワード'
SECRET_KEY_BASE='先程コピーしたsecret_key_base'
```
書き込みができたら esc(エスケープキー)を押下後、`:wq` と入力して内容を保存します。 保存できたら環境変数を適用するために一旦ログアウトします。

```php:ターミナル(EC2)
[ec2-user@ip-172-31-23-189 <アプリ名>]$ exit
logout
Connection to XX.XXX.XXX.XX closed.

# もう一度ログイン
$ ssh -i ダウンロードした鍵の名前.pem ec2-user@Elastic IPアドレス

# 設定した環境変数が適用されているか確認
$ env | grep SECRET_KEY_BASE
SECRET_KEY_BASE='XXXXXXXXXXXXXXXXXXXXXXXXX'

$ env | grep DATABASE_PASSWORD
DATABASE_PASSWORD='XXXXXXXXXXXXX'
```
これで環境変数が設定出来ました！

# 終わりに
ここまでで、EC2インスタンスにSSHログインしてアクセスすることが出来ました。
次回でHTTP通信を可能にしてRailsアプリを起動させる工程まで進めます。
お疲れさまでした。。。

次回
[Railsアプリを起動](https://qiita.com/anago1030/items/36d0da7e25c57d0e5780)