1. はじめに
前回の記事では、AWS CDKを使用してVPCとサブネットを構築しました。
今回はその続きとして、Nuxtで作成したフロントエンドを配置するためのS3バケットを構築します。
最終的には、S3に配置したフロントエンドをCloudFront経由で配信する構成を目指しています。
この記事では、Nuxt SPAの基本的な仕組みを整理したうえで、S3の役割やCDKによるバケットの作成方法、各設定内容について解説します。
2. NuxtとSPAについて
2.1 Nuxtとは?
Nuxtは、Vue.jsをベースとしたWebアプリケーション開発用のフレームワークです。
Vue.jsの機能に加えて、ページのルーティングやレンダリングなど、Webアプリケーションの開発に必要な機能が用意されています。
今回AWSに配置するWebアプリケーションは、Nuxt 4で開発されています。
2.2 SPAとは?
SPA(Single Page Application)は、ページ全体を毎回読み込み直すのではなく、JavaScriptを使用して必要な部分を更新するWebアプリケーションの仕組みです。
一般的なWebサイトとSPAでは、ページ遷移時の動作が異なります。
SPAのメリット
- ページ全体を再読み込みしないため、画面遷移がスムーズになりやすい
- 必要な部分だけを更新できるため、操作性の高いUIを実現しやすい
- フロントエンドとバックエンドをAPIで分離しやすい
SPAのデメリット
- 初回アクセス時にJavaScriptなどの読み込みが必要となり、初期表示が遅くなる場合がある
- JavaScriptへの依存度が高く、ブラウザ側の処理負荷が増える場合がある
- ブラウザ側で画面を描画する構成では、SEO対策が必要になる場合がある
2.3 なぜNuxt SPAをS3に配置できるのか?
今回のNuxtアプリケーションでは、以下の設定により、ブラウザ側で画面を描画するSPA構成を採用しています。
// nuxt.config.ts
export default defineNuxtConfig({
ssr: false,
})
この構成では、ビルドによってHTML・CSS・JavaScriptなどの静的ファイルを生成できます。
S3は静的ファイルを保存できるサービスであるため、Nuxtで生成したファイルの配置先として利用できます。
S3自体はアプリケーションを実行するサービスではありません。
しかし、今回のようなSPAではブラウザ側で画面を描画するため、フロントエンドの配信に常時稼働するNode.jsサーバーを用意する必要がありません。
なお、API処理やデータベースへのアクセスなど、バックエンドの処理が必要な場合は別途実行環境が必要になります。
今回の構成では、フロントエンドにS3とCloudFront、バックエンドにLambdaとAPI Gatewayを使用する予定です。
3. S3とは?
S3は、AWSが提供するオブジェクトストレージサービスです。
画像、動画、HTML、CSS、JavaScriptなど、さまざまなファイルを保存できます。
S3では、保存するファイルを「オブジェクト」、その保存先となる入れ物を「バケット」と呼びます。
今回の構成では、Nuxtで生成した静的ファイルを保存するためにS3バケットを作成します。
3.1 なぜS3を使用するのか?
Nuxt SPAのような静的ファイルを配信する構成では、S3を利用することでサーバーの運用管理を減らせます。
主な理由は以下のとおりです。
- EC2などのサーバーを用意せずにファイルを保存できる
- CloudFrontと組み合わせてWebコンテンツを配信できる
- 保存容量に応じて拡張できる
- AWS CDKで構築・管理できる
3.2 S3とEC2の違い
静的ファイルを配置する方法として、EC2などのサーバーを使用することもできます。
両者の主な違いは以下のとおりです。
| 項目 | S3 | EC2 |
|---|---|---|
| 主な用途 | ファイル保存 | 仮想サーバー |
| OS管理 | 不要 | 必要 |
| Webサーバーの管理 | 不要 | 構成によって必要 |
| アプリケーション実行 | 不可 | 可能 |
| 主な課金要素 | 保存容量・リクエスト等 | インスタンス稼働時間等 |
今回のように静的ファイルの保存先が必要な場合は、S3を使用することでサーバーの運用管理を減らせます。
4. 今回の構成
前回構築したVPCはそのまま残し、今回新たにS3バケットを追加します。
S3はVPC内に配置するサービスではないため、今回作成したPrivate Isolated Subnetには所属しません。
また、今回はS3バケットの作成までを実施します。
CloudFrontを使用したWebコンテンツの配信については、次回の記事で対応します。
5. AWS CDKでS3バケットを作成する
前回作成したsesame-infra-stack.tsにS3の定義を追加します。
5.1 S3モジュールをインポート
まず、S3をCDKで扱うためのモジュールを追加します。
import * as s3 from 'aws-cdk-lib/aws-s3';
aws-cdk-lib/aws-s3は、S3バケットなどのリソースを定義するためのライブラリです。
5.2 S3バケットの定義を追加
続いて、既存のStack内に以下のコードを追加します。
// Nuxt SPAを配置するS3バケット
const frontendBucket = new s3.Bucket(this, 'FrontendBucket', {
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
encryption: s3.BucketEncryption.S3_MANAGED,
enforceSSL: true,
// 検証終了後にS3バケットと中身を削除できるようにする
removalPolicy: cdk.RemovalPolicy.DESTROY,
autoDeleteObjects: true,
});
このコードでは、FrontendBucketという識別子でS3バケットを定義しています。
実際のAWS上のバケット名は、CDKによって自動生成されます。
5.3 各設定の意味
今回指定した設定を整理します。
| 設定 | 内容 |
|---|---|
blockPublicAccess |
S3へのパブリックアクセスをブロック |
encryption |
S3管理キーによるサーバー側暗号化 |
enforceSSL |
HTTPSを使用した通信を要求 |
removalPolicy |
スタック削除時にバケットを削除 |
autoDeleteObjects |
バケット削除時に中身も削除 |
blockPublicAccess
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
S3バケットへのパブリックアクセスを制限する設定です。
主な設定方法は以下のとおりです。
| 設定方法 | 内容 |
|---|---|
BLOCK_ALL |
パブリックアクセスを全面的にブロック |
BlockPublicAccessの個別設定 |
ACLやバケットポリシーに関する制限を個別に指定 |
| 未指定 | S3やCloudFormationのデフォルト設定に従う |
個別に設定する場合は、以下のように指定できます。
blockPublicAccess: new s3.BlockPublicAccess({
blockPublicAcls: true,
blockPublicPolicy: true,
ignorePublicAcls: true,
restrictPublicBuckets: true,
}),
今回はS3を直接公開するのではなく、CloudFront経由でコンテンツを配信する予定です。
そのため、パブリックアクセスを全面的にブロックするBLOCK_ALLを採用しています。
encryption
encryption: s3.BucketEncryption.S3_MANAGED,
S3に保存するオブジェクトを暗号化するための設定です。
主な設定値は以下のとおりです。
| 設定値 | 内容 |
|---|---|
S3_MANAGED |
S3管理キーで暗号化(SSE-S3) |
KMS_MANAGED |
AWS管理のKMSキーで暗号化(SSE-KMS) |
KMS |
ユーザー管理のKMSキーで暗号化(SSE-KMS) |
DSSE_MANAGED |
AWS管理のKMSキーを使用した二重暗号化 |
DSSE |
ユーザー管理のKMSキーを使用した二重暗号化 |
なお、S3では新規オブジェクトに対して、標準でSSE-S3による暗号化が適用されます。
今回は追加のKMSキー管理が不要で、基本的な暗号化を利用できるS3_MANAGEDを採用しています。
enforceSSL
enforceSSL: true,
S3へのアクセス時にHTTPSを要求する設定です。
指定できる値は以下のとおりです。
| 設定値 | 内容 |
|---|---|
true |
HTTP通信を拒否し、HTTPS通信を要求 |
false |
HTTPS通信を強制しない(CDKのデフォルト) |
今回はS3へのアクセス時に暗号化された通信を使用するため、trueを採用しています。
removalPolicy
removalPolicy: cdk.RemovalPolicy.DESTROY,
CloudFormationのスタックを削除した際に、AWSリソースをどのように扱うかを指定する設定です。
主な設定値は以下のとおりです。
| 設定値 | 内容 |
|---|---|
DESTROY |
スタック削除時にリソースを削除 |
RETAIN |
スタック削除後もリソースを残す |
RETAIN_ON_UPDATE_OR_DELETE |
スタック削除や更新時に原則保持し、作成失敗時のロールバックでは削除 |
SNAPSHOT |
削除前にスナップショットを作成(対応リソースのみ) |
S3バケットでは、主にDESTROYとRETAINの違いを理解しておくことが重要です。
RETAINを指定すると、CloudFormationのスタックを削除してもS3バケットはAWS環境に残ります。
一方、DESTROYを指定すると、バケットが削除対象になります。ただし、オブジェクトが残っている場合は、そのまま削除できません。
今回は検証環境であり、構築と削除を繰り返すため、DESTROYを採用しています。
autoDeleteObjects
autoDeleteObjects: true,
S3バケットの削除時に、保存されているオブジェクトを自動削除するかどうかを指定します。
指定できる値は以下のとおりです。
| 設定値 | 内容 |
|---|---|
true |
バケット削除時にオブジェクトも自動削除 |
false |
オブジェクトを自動削除しない(デフォルト) |
通常、S3バケット内にオブジェクトが残っている場合、そのままバケットを削除することはできません。
autoDeleteObjects: trueを指定することで、CDKが削除処理に必要な追加リソースを用意し、バケット内のオブジェクトを削除できるようになります。
なお、この設定を利用するには、removalPolicyをDESTROYにする必要があります。
今回は検証環境を簡単に削除できるようにするため、trueを採用しています。
ただし、本番環境ではデータの消失につながる可能性があるため、慎重に設定する必要があります。
6. CDKの変更内容を確認する
CDKのコードを変更したら、デプロイ前に差分を確認します。
まず、CDKの作業ディレクトリへ移動します。
cd C:\work\sesame-admin\infrastructures\cdk
続いて、以下のコマンドを実行します。
npx cdk diff SesameInfraStack --profile sesame-dev
今回は既存のVPC構成を維持したまま、S3バケットと関連リソースが追加されることを確認します。
6.1 今回想定される差分
S3バケットの追加に伴い、以下のリソースが新しく作成される想定です。
| リソース | 追加される理由 |
|---|---|
AWS::S3::Bucket |
Nuxt SPAの静的ファイルを保存するS3バケット |
AWS::S3::BucketPolicy |
HTTPS通信の強制や自動削除処理に必要なアクセス許可 |
Custom::S3AutoDeleteObjects |
バケット内のオブジェクトを自動削除するための処理 |
AWS::IAM::Role |
自動削除処理用Lambdaに必要な権限を付与 |
AWS::Lambda::Function |
オブジェクトの自動削除処理を実行 |
S3バケット以外にもリソースが追加されるのは、今回autoDeleteObjects: trueを指定しているためです。
CDKでは、この設定を実現するためにLambda関数やIAMロールなどの追加リソースを自動的に用意します。
6.2 実際の差分を確認
実際にcdk diffを実行したところ、以下の差分が表示されました。
想定していた5つのリソースが、すべて[+]として表示されていることを確認できました。
また、IAM Statement Changesでは、HTTPS以外の通信を拒否する設定や、オブジェクトの自動削除に必要なアクセス許可が追加されることも確認できました。
既存のVPCやサブネットに対する削除・変更は表示されていないため、今回の差分は想定どおりと判断できます。
なお、cdk diffはデプロイ前の変更内容を確認するものであり、実際のリソース作成や更新は行いません。
7. AWS環境へデプロイする
差分を確認したら、CDKをデプロイします。
npx cdk deploy SesameInfraStack --profile sesame-dev
cdk deployは、CDKで定義したAWSリソースをCloudFormation経由で作成・更新するコマンドです。
デプロイが正常に完了すると、定義したS3バケットが作成されます。
7.1 AWS CLIでS3バケットを確認
デプロイ後は、AWS CLIを使用してS3バケットが正しく作成されていることを確認します。
今回は以下の項目を確認します。
- S3バケットが作成されていること
- パブリックアクセスがブロックされていること
- サーバー側の暗号化が有効になっていること
① S3バケット名の取得
今回のS3バケットは、CDKによってバケット名が自動生成されるため、CloudFormationから実際のバケット名を取得します。
$bucketName = aws cloudformation describe-stack-resource `
--stack-name SesameInfraStack `
--logical-resource-id FrontendBucketEFE2E19C `
--query "StackResourceDetail.PhysicalResourceId" `
--output text `
--region ap-northeast-1 `
--profile sesame-dev
取得したバケット名を確認します。
Write-Host $bucketName
以降のコマンドでは、取得したバケット名を$bucketNameとして使用します。
② S3バケットの存在確認
以下のコマンドで、S3バケットが存在し、アクセス可能であることを確認します。
aws s3api head-bucket `
--bucket $bucketName `
--region ap-northeast-1 `
--profile sesame-dev
エラーが発生せず、コマンドが正常終了すれば確認完了です。
③ パブリックアクセスの設定確認
以下のコマンドで、S3バケットのパブリックアクセス設定を確認します。
aws s3api get-public-access-block `
--bucket $bucketName `
--region ap-northeast-1 `
--profile sesame-dev
想定される実行結果
{
"PublicAccessBlockConfiguration": {
"BlockPublicAcls": true,
"IgnorePublicAcls": true,
"BlockPublicPolicy": true,
"RestrictPublicBuckets": true
}
}
4つの項目がすべてtrueになっていれば、パブリックアクセスがブロックされていることを確認できます。
④ サーバー側暗号化の設定確認
以下のコマンドで、S3バケットのサーバー側暗号化設定を確認します。
aws s3api get-bucket-encryption `
--bucket $bucketName `
--region ap-northeast-1 `
--profile sesame-dev
想定される実行結果
{
"ServerSideEncryptionConfiguration": {
"Rules": [
{
"ApplyServerSideEncryptionByDefault": {
"SSEAlgorithm": "AES256"
},
"BucketKeyEnabled": false
}
]
}
}
SSEAlgorithmがAES256であれば、S3管理キーによるサーバー側暗号化(SSE-S3)が設定されていることを確認できます。
※ 実際の出力項目は設定や環境によって異なる場合があります。
以上の確認により、CDKで定義したS3バケットが作成され、パブリックアクセスのブロックとサーバー側暗号化が設定されていることを確認できます。
なお、今回はS3バケットの構築が目的のため、Nuxtの静的ファイルのアップロードやCloudFront経由での配信は次回以降に実施します。
8. まとめ
今回は、Nuxt SPAの基本的な仕組みやS3の役割を整理し、AWS CDKを使用してS3バケットを構築しました。
また、各設定項目の意味や採用理由を確認し、CDKによる差分確認からデプロイまでの流れを学びました。
次回は、今回作成したS3バケットとCloudFrontを組み合わせ、Nuxt SPAを配信するための環境を構築していきます。


