DockerでRails環境(Nginx+Unicorn+MySQL)を構築してFargateへデプロイするまで〜本番環境編〜

# 概要
今回は前回の続きで、ECS Fargateへとデプロイを行う本番環境編となっています。

前回の記事：
[DockerでRails環境(Nginx+Unicorn+MySQL)を構築してFargateへデプロイするまで〜開発環境編〜](https://qiita.com/GuChiM1292/items/b7c54ae1b0f831060a70)

# 設定手順
[1. VPC周りの構築](#1-vpc周りの構築)
[2. RDSの構築](#2-rdsの構築)
[3. ECRリポジトリの構築](#3-ecrリポジトリの構築)
[4. ECSの構築](#4-ecsの構築)
[5. アプリのデプロイ](#5-アプリのデプロイ)

## 1. VPC周りの構築
### VPC
|key|value|
|---|---|
|名前|three-mouth-vpc|
|IPv4 CIDR|10.0.0.0/16|

![vpc作成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2131579/ab03eae7-ffb0-cd8c-4df6-af44c89bbcf3.png)




### サブネット
サブネットはECS用のパブリックサブネットと、RDS用のプライベートサブネットをそれぞれ二つずつ作成します。
画像は一つのみの作成ですが、「新しいサブネットを追加」から追加で作成することができます。
|key|value|
|---|---|
|パブリックサブネット①|three-mouth-PublicSubnet-1a|
|アベイラビリティーゾーン|ap-northeast-1a|
|IPv4 CIDR|10.0.10.0/24|

|key|value|
|---|---|
|パブリックサブネット②|three-mouth-PublicSubnet-1c|
|アベイラビリティーゾーン|ap-northeast-1c|
|IPv4 CIDR|10.0.11.0/24|

|key|value|
|---|---|
|プライベートサブネット①|three-mouth-PrivateSubnet-1a|
|アベイラビリティーゾーン|ap-northeast-1a|
|IPv4 CIDR|10.0.20.0/24|

|key|value|
|---|---|
|プライベートサブネット②|three-mouth-PrivateSubnet-1c|
|アベイラビリティーゾーン|ap-northeast-1c|
|IPv4 CIDR|10.0.21.0/24|

![サブネット作成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2131579/f4d7c83a-bd9c-ccbc-a146-1e542f1d0de2.png)


### ルートテーブル
まずはルートテーブルの作成をします。
|key|value|
|---|---|
|VPC ID|three-mouth-vpc|
|名前|three-mouth-route-table|

![ルートテーブル作成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2131579/c256c72e-a025-ac01-1b1a-03cee131c14b.png)



ルートテーブルの作成が完了したら、次にルートの編集を行います。
|key|value|
|---|---|
|送信先|0.0.0.0/0|
|ターゲット|インターネットゲートウェイ|

![ルート編集.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2131579/b86e3c32-ba15-d427-6271-02ae3089c505.png)


ルートの編集が完了したら、最後にサブネットの関連づけを行います。
先ほど作成したサブネットのうち、パブリックサブネットを選択し、関連づけを保存します。
![サブネットの関連づけ1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2131579/35876f53-4a17-e29c-fc27-0cef4e007a03.png)
![サブネット関連づけ2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2131579/9b9026c3-3fac-894f-81c5-49586f41ab2c.png)


### セキュリティグループ
#### ■ ECSのセキュリティグループ
|key|value|
|---|---|
|セキュリティグループ名|three-mouth-SG-ECS|
|説明|Define of SG for ECS|
|VPC|three-mouth-vpc|
|インバウンドルール①|タイプ：HTTP　<br>ソース：0.0.0.0/0|
|インバウンドルール②|タイプ：HTTPS　<br>ソース：0.0.0.0/0|

![SGforECS.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2131579/a48b7dfb-c65a-c602-4fa0-cb490b2b0999.png)

#### ■ RDSのセキュリティグループ
|key|value|
|---|---|
|セキュリティグループ名|three-mouth-SG-RDS|
|説明|Define of SG for RDS|
|VPC|three-mouth-vpc|
|インバウンドルール|タイプ：MYSQL/Aurora　<br>ソース：three-mouth-SG-ECS|

![SGforRDS.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2131579/0d6cdbc7-a08a-d69a-d1d8-c3eca72e1cdb.png)


## 2. RDSの構築
### DBサブネットグループの作成
|key|value|
|---|---|
|名前|three-mouth-subnet-group|
|説明|subnet-group(適当)|
|vpc|three-mouth-vpc|
|アベイラビリティーゾーン|ap-northeast-1a<br>ap-northeast-1c|
|サブネット|10.0.20.0/24<br>10.0.21.0/24|

![DBサブネットグループ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2131579/7476ff29-f302-c7c5-85c8-754ad180afb5.png)



### RDSの作成 
|key|value|
|---|---|
|データベース作成方法|標準作成|
|エンジン|MySQL8.0.28|

![RDS データベース作成方法.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2131579/5c785061-c106-9b1f-b6be-faa89d326497.png)


|key|value|
|---|---|
|テンプレート|無料利用枠|

![RDS 無料枠.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2131579/7823fb0f-abb6-216f-a8ff-a7e347a9dea9.png)

|項目|値|
|---|---|
|DBインスタンス識別子|three-mouth-mysql|
|マスターユーザー名|admin|
|マスターパスワード|password|

![RDS 設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2131579/dd8ea975-fa4f-ad68-f4d2-e1040f780d17.png)

|key|value|
|---|---|
|インスタンスクラス|db.t3micro|
|ストレージタイプ|汎用SSD（gp2）|
|ストレージ割り当て|20|
|最大ストレージしきい値|1000|

こちらは無料利用枠を指定するとデフォルトで入力されるため、特に修正する必要はありません。

![RDS インスタンスの設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2131579/7f1aca2b-b21a-b346-a444-017e0b799605.png)

|key|value|
|---|---|
|VPC|three-mouth-vpc|
|DB サブネットグループ|three-mouth-subnet-group|
|セキュリティグループ|three-mouth-SG-RDS|

![RDS 接続.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2131579/69548cb9-c9dd-10d2-be5e-425168cbbfc3.png)
他の項目については、デフォルトでOKです。入力が完了したら、データベースを作成します。RDSが作成できたらエンドポイントを確認し、メモしておきます（ECS構築時に使用）。
![RDSエンドポイント.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2131579/fd9640d9-9da2-27e2-4fb6-c5cdf8e1dd20.png)



## 3. ECRリポジトリの構築
|key|value|
|---|---|
|リポジトリ名（rails用）|myapp-miguchi-rails|
|リポジトリ名（nginx用）|myapp-miguchi-nginx|

![ECRrails.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2131579/e4f2a282-3efa-7abb-7d01-e0c59c278247.png)
![ECRnginx.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2131579/71ad167c-c773-114c-73d0-d8c29ac48c1d.png)
作成ができたらそれぞれのURIをコピーし、メモしておきます。
こちらもECS構築時に用います。
![ECR URI.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2131579/3dba79aa-1e01-8b1d-c865-7bbc4bf49ad4.png)


## 4. ECSの構築
### タスク定義
タスク定義ではコンテナの数やリソース、コンテナ同士のリンク方法などを定義します。
それでは作成していきましょう。

まずは起動タイプを選択します。
今回はFargateを使用するので、以下の画面で選択し、次のステップへ進みます。
![ECS 起動タイプ選択.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2131579/413a1f63-2765-f65b-cfb7-8e8d9025dabd.png)


次にタスクの定義を行なっていきます。
|key|value|
|---|---|
|タスク定義名|myapp-miguchi|
|タスクロール|ecsTaskEcecutionRole|
|ネットワークモード|awsvpc|
|オペレーティングシステムファミリー|Linux|

![ECS タスクとコンテナの定義.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2131579/f810b076-3265-c9bc-0a42-99f7c0f0a388.png)

|key|value|
|---|---|
|タスク実行ロール|ecsTaskEcecutionRole|
|タスクメモリ|0.5GB|
|タスクCPU|0.25vCPU|

![ECS タスクの実行IAMロール.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2131579/529fdec7-c0f4-deb8-3e34-f8ad3ded8ce2.png)
タスクの定義が完了したら、次はコンテナの定義です。
Rails用のコンテナとnginx用のコンテナの定義をしていきます。
同じ設定画面の「コンテナの定義」から「コンテナの追加」をクリックします。
![ECS コンテナの定義.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2131579/4187bf31-a356-fc63-656c-43595f7fd187.png)


|key|value|
|---|---|
|コンテナ名|rails|
|イメージ|ECR作成時にメモしたURI:latest|
|ポートマッピング|3000|

![ECS コンテナ定義rails1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2131579/28d820fa-c4a6-3bb3-7c9e-6488d8e9ef17.png)


|key|value|
|---|---|
|DB_DATABASE|three-mouth-mysql|
|DB_HOST|RDSのエンドポイント|
|DB_PASSWORD|password|
|DB_USERNAME|admin|
|RAILS_ENV|production|

![ECS コンテナ定義rails2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2131579/ad4f7d45-f617-a174-1bc0-56e9e10ea73e.png)



|key|value|
|---|---|
|コンテナ名|nginx|
|イメージ|ECR作成時にメモしたURI:latest|
|ポートマッピング|80|

![ECS コンテナ定義nginx1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2131579/f8c5e00d-a161-31ee-ec83-c089545203da.png)
![ECS コンテナ定義nginx2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2131579/e35e5af0-dcaa-0860-de51-0d4f7e49b772.png)
![ECS コンテナ定義編集済.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2131579/0e05b774-bbe4-ca43-f383-0d33a9d25802.png)


### クラスターの作成
![ECS クラスター1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2131579/99797557-0eb8-ac88-b175-6a0c2c20339d.png)
![ECS クラスター2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2131579/24c3e0b3-59e8-0511-85d0-60d3c60c872a.png)

## 5. アプリのデプロイ
### Docker Imageのプッシュ
いよいよ、アプリのデプロイです。AWSコンソールにてECRを開きます。Nginx用のリポジトリを選択し、プッシュコマンドの表示を選択します。
![ECRリポジトリ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2131579/acc69b5f-61a2-70e6-558e-085fb4dd8a34.png)
terminalで以下の4つのコマンドを実行し、DockerのイメージをECRにプッシュします。
![ECRプッシュコマンド.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2131579/df8e1a7b-f60f-7ac7-116d-94867016da98.png)
コマンド実行が完了したら、イメージがプッシュされているか、コンソール上で確認します。
確認が完了したら、rails用のリポジトリでも同様の操作を行います。
![ECRイメージ確認.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2131579/8803550c-6724-cf92-614b-3e5d76ed03ca.png)
正直作成をしなくてもよいのですが、私は以下のような本番用docker-composeを作成しました。少しだけデプロイが楽になります（プッシュコマンドの2を実行）。
```terminal:terminal
cd ~/Desktop
touch docker-compose.prd.yml
```
```yaml:docker-compose.prd.yml
version: '3'

services:
  web:
    build:
      context: .
    image: myapp-miguchi-rails
    
  nginx:
    build:
      context: ./nginx
    image: myapp-miguchi-nginx
```
```terminal:terminal
docker-compose -f docker-compose.prd.yml build
```

### ECSデプロイ
Docker Imageのプッシュが完了したら、次はECSのサービスを作成していきます。
AWSコンソールにてECSを開きます。先ほど作成したクラスターを選択し、[サービス]にて[作成]をクリックします。
![ECSクラスターサービス作成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2131579/f45389d9-9ed5-97e7-4fdb-dde10b2478fb.png)
サービスの設定画面ステップ1が表示されるので、以下の項目を入力します。
以下の項目以外の入力欄はデフォルトでOKです。入力が完了したら、次のステップ2に進みます。
|key|value|
|---|---|
|起動タイプ|FARGATE|
|サービス名|myapp-miguchi(適当)|
|タスクの数|1|

![ECSクラスターサービス1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2131579/2cf3ef68-ed69-49ae-25f5-4735ea7624f1.png)
続いて、以下の項目を入力します。入力が完了したら、次のステップ3に進みます。
|key|value|
|---|---|
|クラスター VPC|three-mouth-vpc|
|サブネット|three-mouth-PublicSubnet-1a<br>three-mouth-PublicSubnet-1c|
|セキュリティグループ|three-mouth-SG-ECS|

![ECSクラスターサービス2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2131579/6b13c2ee-86d8-c40c-d41c-3829aac5409b.png)
ステップ3、4では情報の入力はないため、設定の確認ができたら作成します。
作成後は、サービスで確認できます。
![ECSクラスターサービス作成後.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2131579/a51a52b8-6fcc-7116-b566-f4e5ff4b5fed.png)
サービスと同時にタスクも作成されます。
タスクをクリックし、パブリックIPを確認できたら、アクセスしてみます。
![ECSクラスターサービスタスク.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2131579/730dd225-b02f-4f8a-d9cf-effd8252f655.png)
![ECSクラスターサービスタスクIP.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2131579/d2d97574-22fa-06c9-b92a-ce958a83e700.png)
しっかり表示されることが確認できました。
![ECSデプロイproducts.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2131579/9800225e-7e3f-c674-9b8f-bd2bb4a82509.png)
CRUD処理もしっかりできていますね。
![ECSデプロイproducts後.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2131579/8fc458d4-734a-45ae-3a89-3ee855abd3fb.png)
今回はこれで以上です。

# 終わりに
CICDを作成するかも？！