EC2 + RDS + Capistrano + unicorn + nginxでrailsアプリを自動デプロイする【前半】



## 事前準備
・AWSのアカウントを所持している
・GitHubのアカウントを所持している

今回はscaffoldで作成したuserを登録するだけのアプリをデプロイしていきます。

##概要

Capistranoを用いると自分のGitHubにアップしたコードを本番環境にcloneしサーバーを起動し、変更されたコードを反映するといった作業がlocalから一行のコマンドで実行が可能になります。

通常AWSにアプリをデプロイする場合サーバー側にログインしgitで変更したコードをクローンしサーバーを起動しなおすといったことが必要なので、Capistranoを使用すると大幅にデプロイの手間を削減することが可能です。

この記事では0から簡単なアプリを作りAWSの環境を構築し、Capustranoを用いてデプロイを行うまでを解説します。

##開発環境


|     |**version**|
|:---:|:--:|
|OS|　Windows 10|
|  Ruby  |  2.6.5 |
|Rails| 5.1.7|
|Nginx|1.16.1|
|Unicorn|5.5.3|
|Capistrano|3.12.0|
|capistrano3-unicorn|0.2.1|


##アプリ作成

sampleディレクトリを作成し、その配下に

rails new sample_app

で**sample_app**を作成。

その後

```sh:sample/sample_app
rails g scaffold user name:string email:string 

rails db:migrate
```

で作成終了です。
scaffoldってなんて便利なんだ…

# AWSのでのインフラ構築
まずはAWSに本番環境を構築していきます。
今回構築に使用するサービスは以下の4つです。


- **VPC**
- **EC2**
- **RDS**

![AWS deproy.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536448/6f2e5d96-6397-bf81-6ff9-f1167992a329.jpeg)

こちらを順に構築していきます。

##AWS VPC（Amazon Web Service Virtual Private Cloud）

AWSのクラウド上でプライベートに使用できるエリアのことです。このプライベートに使えるエリアを設定しその上で、仮想マシンやネットワーク、データベースを構築していく流れになります。

まずAWSのメニュー画面から「VPC」を選択し画像のようにVPCを作成します。
![スクリーンショット (51)_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536448/5d6d038e-c419-71bc-4c42-dc494390f0da.jpeg)

![スクリーンショット (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536448/4d92bc0e-0cb7-4a10-e9aa-33740ff7b59d.png)

入力項目はそれぞれ

```
 名前タグ: VPCにつける名前
 CIDERブロック:VPCが使用可能なIPの範囲
 テナンシー:　ハードウェアを物理的に独占するかどうかの選択
```
なので
入力項目を以下のように設定しました。


| 設定項目 |  設定   |
|:-----:|:-----:|
|   名前タグ | sample_VPC |
|  CIDR | 10.0.0.0/16 |
|テナンシー|　デフォルト |


### サブネットの作成

![subnet.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536448/3ffcf551-0727-70a3-e8f6-82c69d1f844b.jpeg)

続いてサブネットの設定です。

こちらはVPC内外の通信グループを目的に応じて個別設定するものとなっています。

今回は「VPC内のRDSとプライベートに行う通信」と「localやインターネットで行うパブリックな通信」の2種類(RDSは2つなので合計3つ)のサブネットを作成していきます。
![スクリーンショット (5).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536448/3285959e-01fe-ef31-7ed4-bb1ec4c15abd.png)

### EC2用
![スクリーンショット (6).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536448/5d2d8c4c-329b-3c6a-f81d-7e08d3c05844.png)


VPCは先ほど**自身で作成したもの**を選択してください。
（**他にcloud9等のサービスを使用している場合VPCが複数表示されるので間違えて選択しないように注意**）

こちらで設定。

|       設定項目 |    設定   |
|:-----------------:|:------------------:|
|    名前タグ   |        sample_app_subnet_for_EC2     |
|  VPC | sample_VPC |
|   アベイラビリティ―ゾーン |  us-east-2a        |
|    IPv4 CIDR   |10.0.0.0/16       |
|   IPv6  |       なし |
|   テナンシー|    デフォルト  |

### RDS用

続いてRDS用のサブネットです。
RDS用にはサブネットグループを作成するためアベイラビリティの異なる2種類のサブネットを作っていきます。

|       設定項目 |    設定   |
|:-----------------:|:------------------:|
|    名前タグ   |        sample_app_subnet_for_RDS1    |
|  VPC | sample_app_VPC |
|   アベイラビリティ―ゾーン |  us-east-2a        |
|    IPv4 CIDR   |10.0.2.0/16       |
|   IPv6  |       なし |
|   テナンシー|    デフォルト  |

|       設定項目 |    設定   |
|:-----------------:|:------------------:|
|    名前タグ   |        sample_app_subnet_for_RDS2    |
|  VPC | sample_app_VPC |
|   アベイラビリティ―ゾーン |  us-east-2b    |
|    IPv4 CIDR   |10.0.3.0/16       |
|   IPv6  |       なし |
|   テナンシー|    デフォルト  |


### インターネットゲートウェイ

先ほどサブネットでインターネット接続を行えるよう設定しましたが、インターネットとの入り口である「インターネットゲートウェイ」を設定しないと通信を行うことができません。
上の図の「GW」に当たる部分ですね。

![スクリーンショット (9).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536448/d802c65c-d996-2cd2-bfe5-684051d53fd5.png)

こちらも作成したVPCと紐づけを行います。

![スクリーンショット (11)_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536448/c40dc584-7276-55da-bb13-bab15b29c800.jpeg)

![スクリーンショット (12).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536448/fe98768e-e1a0-e4ca-c9f5-be9584a30d7c.png)


最後に**attached**になっていることを確認したら完了です。

### ルートテーブルの作成

サブネットが設定し終わったのでサブネットとインターネットを繋ぐルートを作成していきます。
![スクリーンショット (13)_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536448/06933fe3-b44c-a346-efa2-a68492bd6588.jpeg)

| 設定項目| 設定|
|:----:|:----:|
|名前タグ| お好みで |
|VPC| sample_VPC|

作成したルートにインターネットゲートウェイを関連付けます。
![スクリーンショット (14)_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536448/ad326bea-bd4a-6f0b-322d-347bbb86e420.jpeg)

![スクリーンショット (15).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536448/cf395259-20e0-7945-dcf0-5ace3f5e66b6.png)

|　設定項目　| 設定 |
|:----:|:----:|
| ターゲット | sample_app_GW |
| 送信先 | 0.0.0.0/0 |

###セキュリティグループ

![routesjpg.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536448/4e2f4d3d-1384-47c9-1763-37dc44927e4b.jpeg)


最後にセキュリティグループを設定します。


このセキュリティグループではどの通信を許可するかを明示的に設定します。こちらは設定した通信以外すべて弾かれてしまうため、漏れのないように設定しましょう。

まずはセキュリティグループを名前を付けて作成し、作成したVPCを適応させます。

### EC2用

|  設定項目　| 　設定　 |
|:--:|:--:|
| セキュリティグループ名 | Security_for_sample_app_EC2 |

![スクリーンショット (54)_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536448/ac904df2-f3dd-aa53-86f5-7ce27d78a593.jpeg)

| 説明 | Security_for_sample_app_EC2 |
| VPC | sample_VPC |


続いてインバウンドルールを開き設定していきます。


|       タイプ |プロトコル | ポート範囲 | ソース　| 
|:-----------------:|:------------------:| :--: |:--: |
|             HTTP  |      TCP     | 80 | 0.0.0./0 |
|            SSH|       TCP      | 443 | MY IP | 
| 全てのICPM-IPv4 |        ICMP    | すべて　| MY IP | 

HTTPは一般的なWebページをやり取りする普通の通信ですね。

対してSSH通信はより安全性の高い通信になっています。
基本的にこれからはSSH通信を使ってサーバーとやり取りをしていくので必ず設定して下さい。

最後は後ほどサーバーが生きているかどうかを確かめる手段として、pingを送信し返答があるかどうかを確かめたいので設定しています。

こちらは必須ではありませんがエラー解決に役立つので設定しておくことをおすすめします。


ここまで設定できれば**VPC**の設定は完了です。

##RDS

### パラメータグループ


それではデータベースのサポートサービスであるRDSの作成も行いましょう。

とその前に、パラメータグループを作成することをおすすめします。これ作成しておくとデータベースに設定されている文字コードなどの設定を変更できるのです。

実はRDSのデフォルト設定では、データベースに日本語を保存できないため日本語を使用するためにはRDSで明示的に設定を行う必要があります。

今回は事前にデータベースに日本語を保存する、サーバーで日本語を表示できるようにするという2つの設定をグループとして作成します。

RDSへ移動→パラメータグループ→パラメータグループの作成

|  **設定項目**　| **設定**  |
|:--:|:--:|
| パラメータグループファミリー　| mysql5.7 |
| グループ名 | for-sample-app-db(お好みで)　|
| 説明 | for-sample-app-db(お好みで) |

![スクリーンショット (53).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536448/06d62b7f-8db7-0041-7e29-e62ac2e49975.png)

**パラメータグループアクション**→**編集**で作成したパラメータを編集します。

**character**で検索をかけて以下パラメータを**utf8**に変更します。

- character_set_database
- character_set_client
- character_set_connection
- character_set_results
- character_set_server

これでデータベースに日本語を保存することができますし、サーバーで文字化けすることもありません。

### データベースの作成

ではRDSでデータベースを作成していきます。

**データベース**→**データベースの作成**


![スクリーンショット (29).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536448/cb133c0d-bb8d-0c12-72cc-90cb014ff4ae.png)

|  設定項目　| 　設定 |
|:--:|:--:|
| エンジンオプション | MySQL |
| テンプレート | 無料利用枠 |

*※注意**
**必ずご自身にあったデータベースプランを選択してください。デフォルトだと結構な利用料金が発生するのでインスタンス作成の際はお気をつけて…**

そのまま下の**設定へ**

![スクリーンショット (30).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536448/2643a6e1-79fb-44a3-3ae6-b5ba205b8dd4.png)


![スクリーンショット (39).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536448/8ce525c9-ae47-4dbb-6680-7e9a9170e9e5.png)
**このVPCに関連するすべてのサブネットを追加します**を選択しそのまま作成
![スクリーンショット (40).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536448/9cbed5fe-793d-4cc4-647e-fff6b6bd146b.png)


インスタンスの作成後はセキュリティグループができるので新たにRDB⇔EC2間のセキュリティグループを設定します。

|  設定項目　| 　設定 |
|:--:|:--:|
| セキュリティグループ名 | Security_for_sample_app_RDS |
| 説明 | Security_for_sample_app_RDS |
| VPC | sample_VPC |

インバウンドルール

|タイプ |プロトコル | ポート範囲 | ソース　| 
|:-------:|:--------:| :--: |:--: |
|         MYSQL/Aurora    |      TCP     | 3306 | EC2に設定したSGのID |

これでRDSとEC2のみで通信を許可するプライベートなセキュリティグループを作成できました。

**設定のまとめ**

**設定**

|  設定項目　| 　設定 |
|:--:|:--:|
| マスターユーザー名 | sample_user |
| マスターパスワード | password |

**接続**

|  設定項目　| 　設定 |
|:--:|:--:|
| Virtual Private Cloud (VPC)　| sample_VPC |
| サブネットグループ | sample_app_subnet_group |
| VPCセキュリティグループ |　Security_for_sample_app_RDS(上記のもの) |
| アベイラビリティゾーン| us-east-2a |

**追加設定**

|  設定項目　| 　設定 |
|:--:|:--:|
|最初のデータベース名| **sample_app_db** |
| DB パラメータグループ | for-sample-app-db(上記のもの)|

※最初のデータベース名は後ほど使用するのでメモすることをおすすめします。一度インスタンスを作成してしまうと確認するのが少し手間になりますので。


##EC2


![ec2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536448/be573e9d-b51d-4789-3427-6d9f8b9dd07b.jpeg)


それではサーバー本体である**EC2インスタンス**を作っていきましょう！

EC2へ移動→インスタンス→インスタンスの作成

|  **項目**　| 　**設定** |
| :--: |:--:|
|　AMI | Amazon Linux 2 AMI (HVM), SSD Volume Type (無料枠対象) |
| インスタンスタイプ |t2.micro (無料枠対象) |

ステップ3

![スクリーンショット (19).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536448/af21c3e1-884e-cf4e-fa40-e76aa5ddd907.png)

|  **項目**　| 　**設定** |
|:--:|:--:|
|　 ネットワーク　| sample_VPC |
| サブネット | sample_app_subnet_for_VPC  |

サブネットは先ほど作成した外部通信が可能な方のサブネットを選択します。


ステップ4

デフォルトのままボリュームは8GiB

ステップ5

タグはお好みで
Name : sample_app_EC2など

**セキュリティグループの設定**
セキュリティグループも同様にSSH通信が可能なものを選択。

確認と作成。


ここで必ず**新しいキーペアを作成**をクリックしキーペアを作成後ダウンロードします。

![スクリーンショット (23).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536448/cac17db5-3a0c-63ad-15d7-ec92090a29ce.png)


これはlocalからSSH接続をする際のキーになるのでlocalの**.ssh/**ディレクトリに移動させておいてください。



###Elastic IP アドレス

最後にこちらを作成。
実はインスタンスのもっているIPアドレスはサーバーを起動する度に変更されてしまい、いちいち設定し直すのはとても現実的とは言えません。

そのためAWSでは**Elastic IP アドレス**というユーザーアカウントに紐付けられるIPアドレスを設定することで、この問題を解決することが可能です。

早速作成していきましょう。

Elastic IP→Elastic IP アドレスの割り当て→　割り当て

これでIPアドレスが生成されたので
![スクリーンショット (25).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536448/a17dab35-5eea-1d4d-b8c3-0da2dd9a0cfb.png)




![スクリーンショット (12).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536448/a8cf4f61-6103-cd2e-be30-06836d863af7.png)
![スクリーンショット (27).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536448/9fdcc46d-e9cb-ca7a-cbd0-9703c7fc682a.png)

|  **項目**　| 　**設定** |
| :--: |:--:|
|　VPC　| sample_VPC |
| プライベートIP | VPCを選択すると自動で選択できます |

AWSのインフラはこれで整ったのでlocalに移動しサーバーとやり取りできるようにSSH接続の設定をしていきましょう。

#local側の設定

まずは先ほど.sshディレクトリに移動させた「.pem」を用いてlocal環境からserver側に接続を行います。

```console:~/.ssh
$ ssh -i sample_app.pem ec2-user@Elastic IP .〇.〇.〇.
```
Amazon Linux2 ではEC2にログインできるuserとしてデフォルトで「ec2-user」が用意されているのでこちらでログインします。
**(Amazon Linux2以外を使用している場合デフォルトで用意されているuserが異なる場合があるため、対応しているuser名でログインして下さい)**

本当に接続しますかと聞かれるので**yes**入力を入力し続行します。

成功

```

       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-2/
```
**上手くいかない場合**

```console
$ ping Elastic IP 
```
でpingを送信して、EC2インスタンスが生きているかを確認します。
その後反応があれば.sshディレクトリにキーペアが存在しているかどうかや、セキュリティグループが自身の端末から接続が可能な設定になっているかを確認してみてください。

なければインスタンスが起動しているかなどをもう一度チェックしてみてください。

###root権限を持つユーザー登録

root権限のまま設定を進めるのは危険なため、権限を持つuserをもう一人追加してから、そのuserでアクセスします。

今回は**sample_user**という名前のuserを追加します。

```console
[ec2-user@ip-10-0-0-110 ~] $ sudo adduser sample_user
#userの登録
[ec2-user@ip-10-0-0-110 ~] $ sudo passwd sample_user
#passwordの登録
[ec2-user@ip-10-0-0-110 ~] $ sudo visudo
#vimで権限にかかわるfileを編集します
```

```
## Next comes the main part: which users can run what software on
## which machines (the sudoers file can be shared between multiple
## systems).
## Syntax:
##
##      user    MACHINE=COMMANDS
##
## The COMMANDS section may have other options added to it.
##
## Allow root to run any commands anywhere
root    ALL=(ALL)       ALL   <=ここの下に追加
sample_user  ALL=(ALL)       ALL  #新たにsample_userを追加
```

その後

```console
[ec2-user@ip-10-0-0-110 ~] $ sudo su - sample_user
```

を実行し

```console
[sample_user@ip-10-0-0-110 ~] $
```
のようにuserが変われば完了です。
###SSH接続設定

ではlocalからSSH接続を使ってログインを行います。

localからSSH接続を行うには秘密鍵と公開鍵を作成し、公開鍵をserver側に渡すことによって認証を行う必要があります。
そのためまずはlocalの.sshディレクトリで鍵を生成。


```console:.ssh/

$ ssh-keygen -t rsa

Enter file in which to save the key (C:\Users\yoshi/.ssh/id_rsa): sample_app_key_rsa
#生成するキーの名前を入力、今回はsample_app_key_rsaで作成

#passphraseは空白のままでも大丈夫なので2回Enterを入力


$ dir(Linuxであればls)

2020/02/26  03:44             1,679 sample_app_key_rsa
2020/02/26  03:44               404 sample_app_key_rsa.pub

#秘密鍵と公開鍵(.pubの方)が生成されていることを確認してください

```

ログイン時の設定はconfigファイルにまとめておくと後々便利です。

```console
$ vim config

---------------------------
Host sample_app_key_rsa 　#ログインに使用する名前を設定
  Hostname 3.21.59.95 #IP
  Port 22
  User sample_user　#ログインするuser名
  IdentityFile ~/.ssh/sample_app_key_rsa #作成した秘密鍵のpath


---------------------------
```

```console:ssh/
$ type(Linuxであればcat) sample_app_key_rsa.pub

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC9gEURKQPRJKCFgi1c7puN+6qbOb1LL7QZ/Gtcit3UQZVUVqPVIXJEG25j6vNvAxC4o3muJyORQdKZOLQxipwtv6fQzwB1+fvmuA9BI98mWPtO5AyN0mAL1B1ONYHVxqXqS4z5s2/6YBhc37ki3RZaI5sxRR2Jq4hQaAcRD5K62J1cKOdbuwhpHxz4P7FC/45Wb~
#公開鍵の中身をコピーします
```

serverへ

```console
[ec2-user@3.21.59.95] cd .ssh
#なければ mkdir .sshで作成

[ec2-user@3.21.59.95] chmod 700 .ssh
# chmod で権限を付与


[ec2-user@3.21.59.95] vim authorized_keys

-----------------------
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC9gEURKQPRJKCFgi1c7puN+6qbOb1LL7QZ/Gtcit3UQZVUVqPVIXJEG25j6vNvAxC4o3muJyORQdKZOLQxipwtv6fQzwB1+fvmuA9BI98mWPtO5AyN0mAL1B1ONYHVxqXqS4z5s2/6YBhc37ki3RZaI5sxRR2Jq4hQaAcRD5K62J1cKOdbuwhpHxz4P7FC/45Wb~
#公開鍵を貼り付ける
-----------------------

[ec2-user@3.21.59.95] chmod 600 authorized_keys

```



最後に先ほど作成した秘密鍵を使って接続ができるかどうか確かめてみてください。

configで設定したホスト名でログインできるはずです。

```
ssh sample_app_key_rsa
```

ここまででようやく設定が完了になります。
長くなってしまったためCapistranoによるデプロイの方法は後半で解説致します。

それではー

[>>EC2 + RDS + Capistrano + unicorn + nginxでrailsアプリを自動デプロイする【後半】](https://qiita.com/ichihara-development/items/1ad4b5d8f29c63bf97f5)