Step2: クラウド2
このStepでは、AWSのデータベース・ストレージ・コンテンツ配信のサービス(RDS・S3・CloudFront・Amplify・Route53・ACM)を学び、Step 1 で構築した sns-camp-api をデータベースに接続してデータベース連携を完成させます。あわせてフロントエンドのアプリケーションを制作物に追加し、フロントエンドから API を呼び出せる状態まで構築します。
1. 講座の履修
AWS講座 の以下の章を実施してください。すでに同等の知識がある場合は、講座の履修はスキップしても構いません。
2. 課題の実施
2.1 目的・背景
Step 1 で構築した sns-camp-api の構成に、データベースを追加してデータベース連携を完成させます。あわせてフロントエンドのアプリケーションを制作物に加え、フロントエンドから API を呼び出してデータベースのデータを扱えるようにします。これにより、Webアプリケーションとしての一連の動作をクラウド上で完成させることが目標です。
| 💡 ポイント |
| 本課題は、要件定義や設計を自分で考えるスキルを高めるため、要件をあえて抽象的に記載しています。進める中で不明点がある場合は、講師への質問 から事前に相談してください。メンタリング当日に「わからなくて進んでいない」状態になると活用できる時間が限られてしまうため、迷ったら途中段階でもこまめに質問を出すことを推奨します。 |
2.2 進め方
本課題は、以下の2段階に分けて進めます。
- 構成図の提出: Step 1 の構成を発展させた新しいインフラ構成図を作成し、提出する。メンターからフィードバックを受け、必要に応じて構成を修正する
- 構築結果の提出: フィードバックを反映した構成図をもとに実際に AWS 上で構築し、動作確認と机上確認を行って提出する
構成図のフィードバックを受けてから構築に進むことで、構成の誤りが構築や以降のStepに波及するのを防ぎます。
2.3 使用するアプリケーション
Step 1 で利用した sns-camp-api に加えて、以下のサンプルフロントエンド(sns-camp-front)を追加して利用してください。
2.4 構築要件
Step 1 の構成を発展させる形で、以下の要件を追加・満たしてください。
ネットワーク
- 後述の RDS を配置するサブネットは、インターネットから切り離されていて、異なる AZ で 2 つ以上配置すること
データベース
- RDS(MySQL 8.0)を使用して sns-camp-api のデータを永続化すること
- 異なる AZ で冗長化すること(Multi-AZ 配置)
フロントエンド配信
- sns-camp-front を以下のいずれかの方法で配信すること(Next.js を使っているため、S3 単体での配信はできません)
- ALB + EC2(EC2 で Next.js サーバを動かし、ALB で振り分ける)
- CloudFront + EC2(EC2 で Next.js サーバを動かし、CloudFront を前段に配置。間に ALB を入れるかは任意)
- Amplify Hosting
- インターネット経由でブラウザからアクセスできること
- フロントエンドから sns-camp-api を呼び出し、データベースのデータを参照・更新できること
セキュリティ
- RDS は、EC2 からの MySQL 通信(3306)のみ受け付けること
- フロントエンドを EC2 で配信する場合、EC2 は配信元(ALB・CloudFront など)からの通信のみ受け付けること
独自ドメイン(任意)
- 独自ドメインを Route 53 で管理し、以下に割り当てて HTTPS でアクセスできること(ACM で証明書を発行して設定する)
- バックエンド API(sns-camp-api)の ALB
- フロントエンド(sns-camp-front)の配信元(ALB / CloudFront / Amplify のいずれか)
| 💡 ポイント |
| 独自ドメインは有料で取得する必要があるため、本課題では任意要件としています。ただし、フロントエンドに Amplify または CloudFront を選んだ場合は、ブラウザが HTTPS で配信されたページから HTTP の API 呼び出しを拒否する(Mixed Content エラー)ため、バックエンド API(sns-camp-api)の ALB も HTTPS 化する必要があり、本要件が実質必須となります。 |
2.5 判定基準
動作確認
sns-camp-front をブラウザで操作し、以下がすべて動作することを確認してください。
- ユーザ登録画面から新規ユーザを登録できる
- ログイン画面からログインできる
- タイムライン画面で新しい投稿を作成でき、一覧に反映される
- 投稿詳細画面で投稿の内容が表示される
- 投稿編集画面で投稿を編集でき、変更が一覧・詳細に反映される
- 投稿を削除でき、一覧から消える
机上確認
以下の内容について、実際の設定画面などを確認し、それがわかるスクリーンショットを取得してください。
- 可用性・スケーリング: Step 1 で確認した可用性・スケーリングの構成が、本Stepの変更でも維持されていること
- 独自ドメイン・HTTPS化(任意要件を実施した場合のみ): 独自ドメイン経由でアクセスできる状態と、HTTPS 通信・SSL 証明書の設定
2.6 課題提出
本課題は構成図と構築結果の2段階に分けて提出します。まず構成図を提出し、メンターからのフィードバックを受けてから、構築結果の提出に進んでください。
構成図の提出
下記内容を提出フォームより提出してください(提出はプレミアムプランでご利用いただけます)。
| 項目 |
内容 |
| 概要 |
今回追加する構成の特徴・採用したサービスを簡潔に記載する |
| インフラ構成図 |
Step 1 の構成を発展させたインフラ構成図を画像ファイルとして添付する |
| 選定理由 |
追加・変更したサービスについて、なぜそのサービスを選んだのかを記載する |
| まとめ |
構成を考える過程で検討したこと、工夫したこと、学んだこと |
構築結果の提出
構成図のフィードバックを反映した上で、実際に構築した結果を提出フォームより提出してください(提出はプレミアムプランでご利用いただけます)。
| 項目 |
内容 |
| 概要 |
今回追加した構成の特徴・採用したサービス・選定理由を簡潔に記載する。構成図の提出から構成を調整した場合は、調整内容と理由もあわせて記載する |
| インフラ構成図 |
構築後の最終的なインフラ構成図を画像ファイルとして添付する |
| 動作確認 |
sns-camp-front での画面操作(ユーザ登録・ログイン・投稿の作成・一覧・詳細・編集・削除)がすべて動作している様子をスクリーンショットで記載する |
| 机上確認 |
可用性・スケーリング構成が Step 1 から維持されていることがわかる画面のスクリーンショットを添付する。任意要件(独自ドメイン・HTTPS化)を実施した場合は、その設定画面のスクリーンショットもあわせて添付する |
| まとめ |
構築中に苦労したこと、工夫したこと、学んだこと |
3. メンタリング報告
以下の内容をメンタリングで報告してください(メンタリングはプレミアムプランでご利用いただけます)。
3.1 講座の振り返り
以下の要素それぞれについて、3つの観点で報告してください。
対象の要素
- RDS
- S3
- CloudFront
- Amplify
- Route53
- ACM
報告観点
3.2 提出課題の説明
提出したインフラ構成図をもとに、以下の内容を報告してください。
- どのような意図でこの構成にしたのか(sns-camp-front のデプロイ手段の選定理由を含む)
- この構成のメリット
- この構成のデメリット(リスク)
4. 構築のヒント
Step 1 で構築した sns-camp-api を RDS に接続する場合の変更点と、sns-camp-front を起動する手順をまとめます。本課題の本質は AWS でのインフラ構築にあり、Linux アプリケーションを動かす部分は本課題の本質的な学習対象ではないため、自力で調べて進めていただいて構いませんが、詰まった場合は以下のヒントを適宜参考にしてください。
4.1 バックエンドを RDS に接続する方法
展開して設定例を表示する
RDS インスタンスの作成
RDS で MySQL 8.0 のインスタンスを作成します。sns-camp-api は起動時に CREATE DATABASE IF NOT EXISTS と CREATE TABLE を自動実行するため、データベースやテーブルを手動で作成する必要はありません。
| 設定項目 |
値 |
設定の基準 |
| エンジン |
MySQL 8.0 |
sns-camp-api が MySQL 8.0 の前提で実装されているため |
| ユーザ名・パスワード |
任意 |
sns-camp-api の環境変数 DB_USER / DB_PASSWORD と揃える |
| サブネットグループ |
VPC のプライベートサブネット |
EC2 からのみアクセスできる構成にするため |
| セキュリティグループ |
インバウンドで EC2 のセキュリティグループからポート 3306 を許可 |
EC2 から RDS に接続できるようにするため |
.env ファイルの作成
sns-camp-api のソースには .env.example が同梱されています。これをコピーして .env を作成し、RDS に合わせた値に書き換えます。
アプリケーションのディレクトリに移動します。
cd /home/ec2-user/sns-camp-api
.env.example をコピーして .env を作成します。
cp .env.example .env
エディタで .env を開き(例: vi .env)、以下の項目を RDS に合わせて書き換えます。
| 変数名 |
値の例 |
説明 |
| DB_HOST |
sns-camp-db.xxxxx.ap-northeast-1.rds.amazonaws.com |
RDS のエンドポイント |
| DB_PORT |
3306 |
RDS のポート(通常は変更なし) |
| DB_USER |
admin |
RDS のマスタユーザ名 |
| DB_PASSWORD |
(設定したパスワード) |
RDS のマスタパスワード |
| DB_NAME |
sns_camp |
使用するデータベース名(自動作成される) |
vi の操作に慣れていない場合は、以下のように cat と heredoc を使って .env を一括で上書きする方法でも代替できます(<...> の箇所を RDS の値に置き換えてから貼り付けてください)。
cat > .env <<EOF
PORT=8080
DB_HOST=<RDSのエンドポイント>
DB_PORT=3306
DB_USER=<RDSのユーザ名>
DB_PASSWORD=<RDSのパスワード>
DB_NAME=sns_camp
JWT_SECRET=your-secret-key-change-in-production
ALLOWED_ORIGINS=*
EOF
systemd から .env を読み込む
Step 1 で作成した systemd サービスに EnvironmentFile= を追加して、.env の中身を環境変数としてプロセスに渡します。/etc/systemd/system/sns-camp-api.service の [Service] セクションに EnvironmentFile= 行を追記してください。
[Unit]
Description=SNS Camp API
After=network.target
[Service]
Type=simple
User=ec2-user
WorkingDirectory=/home/ec2-user/sns-camp-api
EnvironmentFile=/home/ec2-user/sns-camp-api/.env
ExecStart=/usr/local/bin/uvicorn app.main:app --host 0.0.0.0 --port 8080
Restart=on-failure
[Install]
WantedBy=multi-user.target
設定を反映してサービスを再起動します。
sudo systemctl daemon-reload
sudo systemctl restart sns-camp-api
疎通確認
ユーザ登録のエンドポイントが正常に応答すれば、RDS 接続が成功しています。
curl -X POST http://<公開URL>/api/v1/auth/register \
-H "Content-Type: application/json" \
-d '{"username":"testuser","email":"test@example.com","password":"password123","display_name":"テストユーザ"}'
接続に失敗する場合は、以下を順に確認してください。
- RDS のセキュリティグループで EC2 からのインバウンド(3306)が許可されているか
- EC2 と RDS が同じ VPC のサブネットに配置されているか
- 環境変数の値が RDS の設定と一致しているか
4.2 フロントエンドを Linux で動作させる方法
展開してコマンド例を表示する
Linux の上で Next.js アプリケーションを動かした経験がない方向けのコマンド例集です。以下の手順を参考に実行することで、sns-camp-front を仮想サーバ上で動作させるところまで到達できます。
sns-camp-front は Next.js 14 で実装されています。仮想サーバ上で動かす場合、Node.js のインストールと、バックエンドの URL を指す環境変数の設定が必要です。まずローカルで、ダウンロードした sns-camp-front.zip を展開して自分の GitHub リポジトリに push します。その後、仮想サーバ上でそのリポジトリを git clone して配置します。GitHub を使った経験がある方は以下の手順で git clone、まだ GitHub を触っていない方は末尾の「(参考)GitHub を使わずに zip を転送する方法」で進めてください。GitHub の使い方は Git/GitHub 章で学べます。
GitHub リポジトリへの push(ローカルで実施)
GitHub にログインして、新しいリポジトリを作成しておいてください。プライベート・公開のどちらでも構いません。初期ファイル(README や .gitignore)は作成しない設定を推奨します。
ダウンロードした zip をローカルで展開します。
Windowsの場合:
Expand-Archive sns-camp-front.zip -DestinationPath sns-camp-front
Macの場合:
unzip sns-camp-front.zip -d sns-camp-front
展開したフォルダに移動します。
cd sns-camp-front
Git リポジトリを初期化します。
git init -b main
ファイルをステージングしてコミットします。
git add .
git commit -m "Initial commit"
GitHub で作成したリポジトリをリモートとして設定します。<自分のGitHubリポジトリURL> は作成したリポジトリの URL(例: https://github.com/<ユーザ名>/sns-camp-front.git)に置き換えてください。
git remote add origin <自分のGitHubリポジトリURL>
リモートに push します。
git push -u origin main
Node.js 20 のインストール
ここからは仮想サーバ側での操作です。Amazon Linux 2023 の場合は、以下のコマンドで Node.js 20 をインストールできます。
sudo dnf install -y nodejs20
サンプルアプリケーションの配置
ホームディレクトリに移動します。
cd ~
自分の GitHub リポジトリから clone します。
git clone <自分のGitHubリポジトリURL> sns-camp-front
clone したディレクトリに移動します。
cd sns-camp-front
依存関係のインストールとビルド
依存関係をインストールします。
npm install
バックエンド API の公開 URL を指定してビルドします。
NEXT_PUBLIC_API_URL=https://<APIの公開URL>/api/v1 npm run build
サーバの起動
NEXT_PUBLIC_API_URL=https://<APIの公開URL>/api/v1 npm start
NEXT_PUBLIC_API_URL は、ブラウザから見える API の URL を指定します(仮想サーバの内部 DNS ではなく、ALB や CloudFront 経由の公開 URL)。常駐化する場合は sns-camp-api と同様に systemd サービスとして登録してください。
(参考)GitHub を使わずに zip を転送する方法
GitHub がすぐに使えない場合は、ローカルの sns-camp-front.zip を SCP で仮想サーバに転送し、仮想サーバ上で unzip して展開する方法でも代替できます。
ローカルで実施
ローカルから仮想サーバに zip を転送します。<鍵ファイル> は仮想サーバ作成時にダウンロードした .pem ファイル、<仮想サーバのパブリックIP> は仮想サーバのパブリック IP アドレスに置き換えてください。
scp -i <鍵ファイル> sns-camp-front.zip ec2-user@<仮想サーバのパブリックIP>:~/
仮想サーバで実施
unzip をインストールします。
sudo dnf install -y unzip
ホームディレクトリに移動し、zip を展開します。
cd ~
unzip sns-camp-front.zip -d sns-camp-front
cd sns-camp-front
4.3 フロントエンドからバックエンド API に接続する方法
展開して設定例を表示する
sns-camp-front がバックエンド API に接続する URL は、ビルド時引数(NEXT_PUBLIC_API_URL)で指定します。独自ドメインの設定状況に応じて URL を使い分けてください。
| 独自ドメインの設定状況 |
NEXT_PUBLIC_API_URL の例 |
| 独自ドメイン未設定(デフォルトのまま) |
http://<ALBのDNS名>/api/v1(HTTP) |
| 独自ドメイン + HTTPS 化(任意要件を実施) |
https://api.<自分のドメイン>/api/v1(HTTPS) |
NEXT_PUBLIC_* の環境変数は Next.js のビルド時に埋め込まれるため、API の URL を変えた場合は再ビルドが必要です。Amplify を利用する場合は、Amplify Hosting の環境変数で NEXT_PUBLIC_API_URL を設定するとビルド時に注入されます。
4.4 Amplify Hosting で配信する方法
展開して設定例を表示する
Amplify Hosting で sns-camp-front を配信する場合、GitHub リポジトリと連携してビルド・デプロイを自動化します。
Amplify アプリケーションの作成
マネジメントコンソールの AWS Amplify を開き、「新しいアプリ」→「ホスティングを開始」から以下の手順で作成します。
| 設定項目 |
値 |
設定の基準 |
| ソース |
GitHub |
sns-camp-front をプッシュしたリポジトリと連携するため |
| リポジトリ・ブランチ |
sns-camp-front のリポジトリと対象ブランチを選択 |
ビルド対象を指定するため |
| ビルド設定 |
Next.js を自動検出(デフォルトのまま) |
Amplify Hosting が output: 'standalone' に対応しているため |
環境変数 NEXT_PUBLIC_API_URL |
API の公開 URL(例: https://api.<自分のドメイン>/api/v1) |
ビルド時にフロントに埋め込むため |
保存すると初回ビルドが始まり、完了するとデフォルトドメイン(https://<ブランチ名>.<ID>.amplifyapp.com)が払い出されます。
独自ドメインの割り当て(任意要件を実施する場合)
Amplify アプリの「ドメイン管理」から独自ドメインを追加し、Route 53 で管理する独自ドメインに割り当てます。Amplify Hosting はデフォルトで ACM 証明書の発行・HTTPS 化を自動で行います。
再デプロイ
GitHub の指定ブランチに push すれば、Amplify Hosting が自動でビルド・デプロイを実行します。NEXT_PUBLIC_API_URL の値を変更した場合は、Amplify の画面から「再デプロイ」を実行してください(環境変数はビルド時に埋め込まれるため、変更後は再ビルドが必要)。
4.5 オートスケーリングでの起動方法(フロントエンド)
展開してユーザデータの例を表示する
sns-camp-front を Auto Scaling グループで起動する場合、Step 1 の sns-camp-api と同じく、Launch Template の「ユーザデータ」にセットアップスクリプトを設定しておくと、新しいインスタンスの初回起動時に自動実行されます。
以下のスクリプトを Launch Template の「ユーザデータ」に設定してください。<自分のGitHubリポジトリURL> は自分のリポジトリ URL に、<APIの公開URL> は sns-camp-api の公開 URL に書き換えてください。
#!/bin/bash
set -eux
dnf install -y git nodejs20
cd /home/ec2-user
sudo -u ec2-user git clone <自分のGitHubリポジトリURL> sns-camp-front
cd sns-camp-front
sudo -u ec2-user npm install
sudo -u ec2-user NEXT_PUBLIC_API_URL=https://<APIの公開URL>/api/v1 npm run build
cat > /etc/systemd/system/sns-camp-front.service <<EOF
[Unit]
Description=SNS Camp Front
After=network.target
[Service]
Type=simple
User=ec2-user
WorkingDirectory=/home/ec2-user/sns-camp-front
Environment=NEXT_PUBLIC_API_URL=https://<APIの公開URL>/api/v1
ExecStart=/usr/bin/npm start
Restart=on-failure
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now sns-camp-front
ユーザデータは EC2 の初回起動時に root ユーザとして実行されます。実行ログは EC2 インスタンス内の /var/log/cloud-init-output.log で確認できます。
4.6 CloudFront + EC2 構成のセキュリティ強化(参考)
展開して概要を表示する
CloudFront + EC2 構成では、CloudFront を迂回して EC2(または ALB)に直接アクセスされてしまうと、CloudFront で設定したキャッシュ・WAF などが素通しになります。本課題の必須要件ではありませんが、本番運用では以下のような対策で CloudFront 経由のアクセスのみに限定する考え方があります。
| 方法 |
概要 |
| CloudFront のプレフィックスリストで SG 制限 |
ALB・EC2 のセキュリティグループで、AWS 提供のプレフィックスリスト com.amazonaws.global.cloudfront.origin-facing からの通信のみ許可する |
| カスタムヘッダーでオリジン認証 |
CloudFront → Origin リクエストに特定のヘッダーを付与し、ALB のリスナールールまたはアプリ側で検証する |
| VPC オリジン |
CloudFront が VPC 内のプライベートリソース(ALB)を直接オリジンにできる機能。ALB をプライベート化できる |
Step 2 の履修講座では扱っていないトピックです。本番運用に近づける場合は、AWS 応用講座やセキュリティ対策講座で学んだ後に取り組むとよいです。
4.7 独自ドメインと HTTPS 化(ALB)の設定方法
展開して設定例を表示する
任意要件の「独自ドメイン・HTTPS化」のうち、バックエンド API(ALB)の HTTPS 化手順の例です。独自ドメインを Route53 で管理している前提で記載しています。
ACM で証明書を発行する
ALB で HTTPS を終端するには、ACM の証明書が ALB と同じリージョン(東京: ap-northeast-1) で発行されている必要があります。CloudFront 用の証明書とは別に、東京リージョンで発行してください。
マネジメントコンソールの ACM(東京リージョン)→ 「証明書をリクエスト」→ 「パブリック証明書をリクエスト」を選び、以下の値で作成します。
| 設定項目 |
値 |
設定の基準 |
| 完全修飾ドメイン名 |
api.<自分のドメイン> |
API 用のサブドメインを割り当てる |
| 検証方法 |
DNS 検証 |
自動化しやすいため |
発行後、ACM の画面で「Route 53 でレコードを作成」ボタンを押すと、検証用の CNAME レコードが Route53 に自動で追加されます。数分待つと証明書のステータスが「発行済み」になります。
ALB に 443 リスナーを追加する
マネジメントコンソールの EC2 → ロードバランサー → 対象 ALB → 「リスナー」タブ → 「リスナーを追加」から設定します。
| 設定項目 |
値 |
設定の基準 |
| プロトコル |
HTTPS |
HTTPS で受け付けるため |
| ポート |
443 |
HTTPS の標準ポート |
| デフォルトアクション |
既存のターゲットグループに転送 |
既存の HTTP リスナーと同じターゲットグループを選択 |
| セキュリティポリシー |
ELBSecurityPolicy-TLS13-1-2-2021-06(推奨) |
モダンな TLS バージョンを使うため |
| ACM 証明書 |
先ほど発行した証明書を選択 |
ALB で HTTPS を終端するため |
あわせて、ALB のセキュリティグループで 443 ポートのインバウンドを許可してください。
Route 53 で ALB にエイリアスを張る
マネジメントコンソールの Route 53 → 対象のホストゾーン → 「レコードを作成」から以下を作成します。
| 設定項目 |
値 |
設定の基準 |
| レコード名 |
api |
api.<自分のドメイン> でアクセスできるようにする |
| レコードタイプ |
A |
ALB にはエイリアス(A レコード)でルーティングする |
| エイリアス |
ON |
ALB の DNS 名を直接指定するため |
| トラフィックのルーティング先 |
Application and Classic Load Balancer → 東京リージョン → 対象の ALB |
ALB にリクエストを転送する |
動作確認
以下のコマンドで HTTPS 経由で疎通確認します。
curl -i https://api.<自分のドメイン>/health
HTTP/2 200 と {"status":"ok"} が返れば完了です。