AWS Management Console 上での環境構築と動作確認
IaC を利用せず、AWS Management Console 上に直接環境構築を行う手順を説明したキュメントです。Lambda Web Adapter の仕組みに慣れていない場合、AWS CloudFormation など IaC を利用する前に、先にこちらの内容を元に構築を進めてみることをお勧めします。
事前に必要なAWSリソースを作成する
デプロイに際して、まずは以下のリソースを作成しておきます。
ECR リポジトリ作成
フロントエンドのコンテナイメージをプッシュする ECR(Elastic Container Registry)のリポジトリを作成します。AWS マネジメントコンソールにログインして、検索窓から「ECR」を入力し、以下の画面から新規リポジトリを作成します。
検証用ではリポジトリ名のみを入力し、他の設定はそのまま作成に進みます。イメージタグの上書き可否や暗号化に関しては案件に合わせて適宜設定してください。
作成したリポジトリの名前で検索して、リポジトリ名をクリックします。
プッシュコマンドの確認ボタンを押して、コマンド一覧が表示されることを確認します。ここに表示されているコマンドは後ほどデプロイ作業時に利用しますが、まずはコマンド表示ができる場所だけ押さえておきましょう。ゼロベースでこれらのコマンドを考えたり、編集する必要はありません。
Lambda@Edge の作成
CloudFront -> Lambda Function URL へのアクセス時に、Lambda Function URL のIAM 認証を解決する必要があります。GET リクエストに関しては CloudFront 標準の OAC (Origin Access Control) で解決することが可能ですが、POST/PUTなど Request Body が含まれるリクエストに関しては OAC に加えてコンテントペイロードの署名を含む( x-amz-content-sha256 )必要があります。
以下、AWS Lambda のコンソールから新規の関数を作成します。注意点として、Lambda@Edge は us-east-1 リージョンで作成する必要があるため、他のリージョンで作成していた場合はリージョンを切り替えてください。
関数名を入力し、ランタイムは Node.js 22、アーキテクチャは x86 になっていることを確認して、関数を作成します。
作成済みの AWS Lambda コンソール上で、以下のようにコードを編集します。
export const handler = async event => {
const request = event.Records[0].cf.request
if (!request.body?.data) {
return request
}
const payload = request.body.data
const decoded = Buffer.from(payload, 'base64').toString('utf-8')
const digest = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(decoded))
const byteArray = Array.from(new Uint8Array(digest))
let hash = ''
for (const bytes of byteArray) {
hash += bytes.toString(16).padStart(2, '0')
}
request.headers['x-amz-content-sha256'] = [
{
key: 'x-amz-content-sha256',
value: hash
}
]
return request
}
コードを入力したらデプロイボタンを押して更新します。
続いて、Configuration > Permission にてロール名をクリックします。
信頼関係(Trust Relationships)タブをクリックして編集ボタンを押します。
編集画面には以下のように Statement.Principal.Service
を配列に変更し、 edgelambda.amazonaws.com
を追加します。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": [
"lambda.amazonaws.com",
"edgelambda.amazonaws.com"
]
},
"Action": "sts:AssumeRole"
}
]
}
ひとまずこれで Lambda@Edge の準備は完了です。
React Router v7 のビルド
Remix v2 が React Router に合流し、React Router v7 からフレームワーク(SSR)とライブラリー(SPA)の両方の使い方ができるようになりました。ここからは、フレームワークモードの利用を前提としてビルドします。
Lambda Web Adapter を利用したコンテナイメージ作成 に記載されている Dockerfile を確認し、ECR リポジトリを作成した際に表示されたコマンドを開き、Docker のビルドとプッシュを行います。
AWS Lambda および Amazon CloudFront を作成、デプロイする
ここから、本格的なデプロイ作業をしていきます。まずは、コアとなる AWS Lambda 関数を作成します。AWS マネージドコンソールから AWS Lambda を開き、関数の新規作成ボタンを押してください。
※「Architecture」項目に関しては、Docker イメージを作成した環境に合わせてください。例えば、m1/m2 mac や t4g
など AWS Graviton プロセッサーを利用するインスタンスタイプ環境でビルドしたコンテナイメージの場合は arm64
になります。それ以外では、通常は、 x86_64
を選択します。
作成した直後では、以下のようにデフォルトのメモリサイズやタイムアウトの値が小さすぎるため、Edit ボタンを押してそれぞれ 256MB
・ 20秒
に設定します。また、以下の画面より、Function URL を設定します。
以下のように選択して Function URL を作成します。
作成が完了すると、以下のように Function URL を確認することができます。
続いて、CloudFront Distribution を作成します。Amazon CloudFront のコンソールを開き、Distribution の作成ボタンを押します。
Origin の項目に作成した Lambda Function URL を入れ、Create new OAC ボタンをクリックします。
ダイアログが表示されますが、特に操作する項目はなく、デフォルトのまま作成ボタンを押して進めます。
下の方にスクロールしていくと、AWS WAF と Description を入力する部分を以下のように設定してください。WAF の場合は CloudFront を作成した後でも必要に応じて適宜有効にして設定することが可能です(IPアドレス制限・bot対策・各種攻撃に対応できる AWS Managed Rule の設定等が可能です)。Description は、作成した Distribution がどのアプリにつながっているかを一覧でわかりやすくするため、なるべくわかりやすい名前にしておいてください。
ここまできたら、画面最下段にある作成ボタンで Distribution を作成します。作成直後、画面上に OAC を有効にするための CLI コマンドのコピーボタンが表示されますので、コピーしてターミナルから実行します。
展開してみると以下のようになりますので、 <YOUR_FUNCTION_NAME>
にコンテナイメージを適用した Lambda 関数名を指定します。
aws lambda add-permission \
--statement-id "AllowCloudFrontServicePrincipal" \
--action "lambda:InvokeFunctionUrl" \
--principal "cloudfront.amazonaws.com" \
--source-arn "arn:aws:cloudfront::000011112222:distribution/E1234ABC5D0EFG" \
--region "us-east-1" \
--function-name <YOUR_FUNCTION_NAME>
最後のステップとして、Lambda Function URL へのアクセス時の IAM 認証を解決するため、Content Hash を付け加える Lambda@Edge を有効化します。 us-east-1 にてLambda@Edge 用に作成しておいた関数を開き、右上の Actions ボタンから Lambda@Edge へのデプロイを行います。
表示されたダイアログでは以下のように入力し、デプロイボタンを押します。
設定はこれで一通り完了です。
動作確認を行う
ここまで設定ができたら、数分ほどで CloudFront のデプロイが行われ、完了表示を確認してから CloudFront が発行したドメインを開きます。
以下のように表示されていれば完了です。以降は、リリース作業として、AWS Lambda のコンテナイメージをプッシュして、Lambda を更新していくだけの運用が可能です。