railsとnginxとAWSとPostgreSQLのデータベース設計入門

# はじめがき
僕は`rails`で作成したアプリを`aws`にデプロイしたいなと思い`aws`を触ったもののエラーにつまりまくり、挫折しまくりました。

そして何とか`rails`アプリを`aws`にアップすることができました。

初心者ですので、間違っている箇所もたくさんあると思いますが、指摘していただけると勉強になります。

この記事が少しでも役に立つと思って記事を書きました。長くなったのですが、読んでいただけると幸いです。



# 1.ネットワーク設計
### ネットワーク設計の全体像

![スクリーンショット 2025-05-06 113242.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3750795/07596735-0aae-4ec5-85b1-02687222deac.png)

:::note alert
NAT-ゲートウェイは必ず`パブリックサブネット`に配置する必要がある。`プライベートサブネット`に置いてもインターネットに出られない。

`パブリックサブネット`に`NAT-ゲートウェイ`はおいており、`プライベートサブネット`の`ルートテーブル`にNAT-ゲートウェイをひもづけている。

`パブリックサブネット`が複数ある場合は、NAT-ゲートウェイを置く`パブリックサブネット`はどちらでもよい。
両方に置いた方が`高可用性`が高い。
:::

:::note alert
`高可用性`のために、パブリックサブネットとプライベートサブネットを異なるアベイラビリティゾーンに分散させるべきである。
:::

### やり方
①まず`VPC`を作成して、そこに`パブリックサブネット`と`プライベートサブネット`を2つずつ作成する。

②`パブリックサブネット`に紐づける`ルートテーブル`を作成する。

③`パブリックサブネット`に紐づける`ルートテーブル`に`インターネットゲートウェイ`を作成して紐づける。

④`パブリックサブネット`に`ルートテーブル`を紐づける。

⑤`NAT-ゲートウェイ`を`パブリックサブネット`上に作成する。

⑥`プライベートサブネット`に紐づける`ルートテーブル`を作成する。

⑦`プライベートサブネット`に紐づける`ルートテーブル`に`natゲートウェイ`を紐づける。

⑧`プライベートサブネット`に`ルートテーブル`を紐づける

これが大体の流れである。

# 2.ロードバランサー設計
### ロードバランサー設計の全体像
![スクリーンショット 2025-05-06 122355.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3750795/aa9ea81f-9bed-4c64-b4c9-d79df4a9324d.png)

### やり方
①ロードバランサーをさっき作った`VPC`内に作り、さっき作った`パブリックサブネット`を2つ配置する。

②`セキュリティグループ`の`インバウンドルール`は`HTTP:80`と`HTTPS:443`を`0.0.0.0/0`ですべての通信を許可する。

:::note warn
開発時は`0.0.0.0/0`はセキュアでないので、`自分のIPアドレス/32`にすべきである。
:::


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3750795/3b2ea12c-56d6-491d-a1a1-bbe8636e791b.png)


③`アウトバウンドルール`はすべての通信を許可する。

④`リスナー`は`HTTP:80`と`HTTPS:443`を設定する。

⑤リスナーの`HTTP:80`は`HTTPS:443`にリダイレクトするようにする。

⑥`ターゲットグループ`は`HTTP:80`と設定して、ヘルスチェックは`/up`とする。

⑦リスナーの`HTTPS:443`に`ターゲットグループ`をひもずける。

# 3.RDSの設計
### RDSの全体像

![スクリーンショット 2025-05-06 233253.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3750795/72356b76-a912-43c4-9c76-74c5c9a33500.png)

### やり方
`データベースのタイプ`：PostgreSQLを使う

`データベースの認証情報管理`：AWS Secrets Managerを使う。

`パブリックアクセス`：なし

`VPC`：今回のvpcを設定する

`セキュリティグループ`：データベースのセキュリティグループを作成する

`データベースのセキュリティグループのインバウンドルール`：

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3750795/150cf1ab-5cb4-4a37-ba26-2c6b05d78a62.png)

`データベースのセキュリティグループのアウトバウンドルール`：すべてのトラフィックを許可


# 4.ECSの設定
### ECSの全体像

![スクリーンショット 2025-05-06 150951.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3750795/5f110f8c-2987-497b-9d10-7d16611627f5.png)

### やり方
①まず`タスク定義`を設定する。

②作った`VPC`を設定する。

③`プライベートサブネット`を2つひもづける。

④`rails`の`セキュリティグループ`を作成する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3750795/9c7de0dd-c061-4314-b1cc-53660b9239eb.png)
`アウトバウンドルール`：すべてのトラフィックを許可

⑤`nginx`の`セキュリティグループ`を作成する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3750795/a8b53bae-bc1a-4dbd-a8a2-685de083585c.png)
`アウトバウンドルール`：すべてのトラフィックを許可



⑥`パブリックIP`を`オフ`にする。

⑦作った`ロードバランサー`を設定する。

# 5.ECRの設計
### ECRの全体像
![スクリーンショット 2025-05-07 210225.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3750795/752e190e-74ee-4721-9366-e1d9d2b922df.png)

### やり方
①`ECR`に`nginx`と`rails`の`ECR`を作成する。
②それぞれの`ECR`にコードをプッシュする。

# 6.Task定義の設計
## Task定義の概要
`起動タイプ`：AWS Fargate


`オペレーティングシステム/アーキテクチャ`：Linux/X86_64

`タスクサイズ`：CPU：.5 v　メモリ：1 GB

`タスクロール`：`secretsmanager:GetSecretValue` アクションを実行できるタスクロールを選択する

:::note info
`rails`のマスターキーやRDS（PostgreSQL）のパスワードを取得するため
:::
タスクロールにこのポリシーをくっつける
```:ポリシー
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "secretsmanager:GetSecretValue",
            "Resource": [
                "RDSのパスワードを保存しているAWS Secrets Manager
のシークレットの ARN",
                "railsのマスターキーを保存しているAWS Secrets Manager
のシークレットの ARN"
            ]
        }
    ]
}
```


### nginxのTask定義
`必須コンテナ`：はい
`ポートマッピング`：HTTP:80
`ログ収集`：オン

### railsのTask定義
`必須コンテナ`：はい
`ポートマッピング`：TCP:3000
`ログ収集`：オン
`環境変数`：

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3750795/8307ee47-3ec1-443d-875f-60a0a6c3dded.png)

# 7.Secrets Managerの設計
### Secrets Managerの概要
`Secrets Manager`には`railsのマスターキー`と`RDSのパスワード`を保存する。
### railsのマスターキー
railsのマスターキーは開発環境の場合(`RAILS_ENV=development`)は、`config/master.key`の中にあるため、その値を`Secrets Manager`に保存する。

Railsアプリの設定ファイル（`config/credentials.yml.enc`など）は暗号化されており、これを復号するための鍵が`config/master.key`である。


環境ごとにcredentialsを分ける場合は以下のように管理する：

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3750795/b110f30c-5364-438b-bd8b-79628641b75a.png)

:::note alert
`config/master.key`はGITHUBやECRにpushするのは危険なので、`.dockerignore`と`.gitignore`に`config/master.key`のファイル名を記入することでpushされないように設定すべきである。
:::

### RDSのパスワード
`RDSのパスワード`はRDSが自動で作ってくれるため、作らなくてよい。

# 8.S3の設計
### S3の概要
`S3`を作成し、`Railsアプリ`が`S3`にアクセスできるようにするには、`S3アクセス権限`を持つ`ポリシー`を`タスクロール`に`アタッチ`する。

### S3の作り方
| 設定項目           | 内容                                |
| -------------- | --------------------------------- |
| バケットタイプ        | 汎用                                |
| バケット名          | 好きな名前（例：tech-books-circle-bucket） |
| オブジェクト所有者      | ACL 無効（推奨）                        |
| パブリックアクセスのブロック | すべてブロックにチェック                      |
| バージョニング        | 無効にする                             |
| デフォルトの暗号化      | Amazon S3 マネージドキー（SSE-S3）         |
| バケットキー         | **（SSE-KMSを使うときのみ有効）**            |

### タスクロールの設定のやり方
① `IAM` → 「ポリシー」 → 「ポリシーを作成」

② 「JSON」タブを開き、以下を入力：

```:ポリシー
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:PutObject",
                "s3:DeleteObject"
            ],
            "Resource": "arn:aws:s3:::ここに自分が決めたS3のバケット名を書く/*"
        }
    ]
}
```

③ 適切な`ポリシー名`をつけて作成する。

④ 作成した`ポリシー`を、`Railsアプリ用のタスク定義`で使っている`タスクロール`に`アタッチ`する。

これにより、`Railsアプリ`が`S3バケット`にアクセスできるようになる。