Amazon S3 + CloudFrontで静的サイトを配信する - CodePipelineによるCI/CD構築

どうも、Shinyaです。この記事では、Docusaurusで作成した静的サイトのリソースをAmazon S3にオリジンとして配置し、Amazon CloudFrontで配信する構成の構築手順について解説します。AWS CodeCommit、CodeBuild、CodePipelineを組み合わせたCI/CDパイプラインにより、コンテンツの管理からビルド・配信までをAWSエコシステム内で完結させています。
- Amazon S3 + CloudFrontで静的サイトを配信したい人
- AWS CodePipelineを使ったCI/CDパイプラインに興味がある人
- Docusaurusで作成したサイトをAWSにデプロイしたい人
- AWSエコシステム内でコンテンツ管理から配信まで一貫して構築したい人
この記事は、WordPressからDocusaurusへの移行記事の続編です。移行の経緯や技術選定の背景については、そちらの記事で解説しています。
全体構成
今回構築するシステムは、以下のAWSサービスで構成されています。
| サービス | 役割 |
|---|---|
| AWS CodeCommit | Gitリポジトリによるソースコード・コンテンツの管理 |
| AWS CodePipeline | CodeCommitへのプッシュ検知からCodeBuild実行までのパイプラインオーケストレーション |
| AWS CodeBuild | Docusaurusの静的サイトビルドとS3への成果物配置 |
| Amazon S3 | ビルド成果物のオリジンストレージ |
| Amazon CloudFront | CDNによるコンテンツ配信 |
コンテンツ作成から配信までのフロー
この構成の利点
- S3 + CloudFrontの組み合わせは、静的サイトホスティングにおけるAWSの標準的な構成パターン
- S3のイレブンナイン(99.999999999%)の耐久性により、データの高い保全性を確保できる
- CodeCommit、CodePipeline、CodeBuild、S3、CloudFrontとAWSエコシステム内でコンテンツ管理から配信まで完結できる
- 将来的にリリースされるAWSサービスとの統合も期待できる
S3バケットの作成
最初に、CloudFrontのオリジンおよびCodeBuildのビルド成果物の配置先として機能するS3バケットを作成します。
AWS CLIを使用してバケットを作成します。バケット名はAWS全体で一意である必要があります。
aws s3 mb s3://YOUR-BUCKET-NAME
バケットが作成されたことを確認します。
aws s3 ls s3://YOUR-BUCKET-NAME
パブリックアクセスの遮断
S3バケットはデフォルトでパブリックアクセスがすべてブロックされています。この設定により、S3バケットのURLに直接アクセスしてもコンテンツを取得することはできません。
コンテンツへのアクセスはCloudFront経由に限定されます。CloudFrontでディストリビューションを作成しS3をオリジンとして指定すると、CloudFrontがOrigin Access Control(OAC)を通じてS3バケットにアクセスするためのポリシーを自動的に設定します。
この構成には以下のセキュリティ上の利点があります。
| 項目 | 説明 |
|---|---|
| パブリックアクセスの遮断 | S3バケットへの直接アクセスがブロックされ、意図しないコンテンツの公開を防止 |
| CloudFrontへのアクセス集約 | すべてのリクエストがCloudFrontを経由するため、WAFやアクセスログなどのセキュリティ機能を一元的に適用可能 |
| OACによるアクセス制御 | CloudFrontのみがS3バケットにアクセスできるポリシーが自動設定される |
S3のパブリックアクセスブロックはデフォルトで有効なため、バケット作成後に追加の設定は不要です。CloudFrontのディストリビューション作成時にOACとバケットポリシーが自動的に構成されます。
CodeCommitでのソースコード管理
今回の構成では、AWSエコシステムへの統合を目指し、AWS CodeCommitでWebサイトのソースコードと記事コンテンツを管理しています。CodeCommitはAWSが提供するマネージドGitリポジトリサービスで、GitHubなどと同じGitベースの操作が可能です。
まず、CodeCommitにリポジトリを作成し、Docusaurusプロジェクトのソースコードをプッシュします。
buildspec.ymlの配置
後述するCodeBuildでビルドを実行するために、buildspec.ymlをリポジトリのルートに配置します。buildspec.ymlはCodeBuildが参照するビルド仕様ファイルで、ビルドの各フェーズで実行するコマンドを定義します。
以下は、Docusaurusプロジェクトで使用しているbuildspec.ymlの例です。
version: 0.2
phases:
install:
runtime-versions:
nodejs: 24
commands:
- npm install
build:
commands:
- npm run build
post_build:
commands:
- aws s3 sync ./build s3://YOUR-BUCKET-NAME/ --delete
artifacts:
files:
- 'build/**/*'
name: BuildArtifact
cache:
paths:
- 'node_modules/**/*'
各セクションの役割は以下の通りです。
| セクション | 役割 |
|---|---|
phases.install | Node.js 24のランタイムを指定し、npm installで依存パッケージをインストール |
phases.build | npm run buildでDocusaurusの静的サイトをビルド |
phases.post_build | aws s3 syncでビルド成果物をS3バケットに同期。--deleteフラグにより、S3上の不要なファイルも削除される |
artifacts | ビルド成果物の出力先を定義 |
cache | node_modulesをキャッシュし、次回以降のビルドを高速化 |
YOUR-BUCKET-NAMEの部分は、先の手順で作成したS3バケットの名前に置き換えます。
CodeBuildによるビルド環境の構築
AWS CodeBuildでビルドプロジェクトを作成し、CodeCommitのリポジトリからソースを取得して静的サイトをビルドする環境を構築します。
ビルドプロジェクトの作成
CodeBuildの管理画面からビルドプロジェクトを作成します。設定のポイントは以下の通りです。
- プロジェクト名: 一意のプロジェクト名を設定
- ソースの設定: ソースプロバイダに「CodeCommit」を選択し、ビルド対象のリポジトリとブランチを指定
- 環境の設定: OSは「Linux」、ランタイムは「Standard」、イメージは「aarch64」の最新バージョンを選択
- サービスロール: 「新しいサービスロール」を選択し、自動作成されるロールを使用
- Buildspec: 「buildspecファイルを使用する」を選択(リポジトリルートの
buildspec.ymlが参照される)
S3アクセス用のIAMポリシー設定
CodeBuildで自動作成されるサービスロールには、S3への操作権限が含まれていません。buildspec.ymlのpost_buildフェーズでS3バケットへの同期を実行するために、以下のカスタムポリシーを作成し、サービスロールにアタッチします。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowS3SyncForBuild",
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:ListBucket",
"s3:DeleteObject"
],
"Resource": [
"arn:aws:s3:::YOUR-BUCKET-NAME",
"arn:aws:s3:::YOUR-BUCKET-NAME/*"
]
}
]
}
このポリシーをアタッチしないと、CodeBuildの実行時にS3バケットへのアクセスが拒否され、post_buildフェーズでエラーが発生します。ビルドログにAccess Deniedが表示された場合は、サービスロールのポリシー設定を確認します。
各アクションの用途は以下の通りです。
| アクション | 用途 |
|---|---|
s3:PutObject | ビルド成果物のアップロード |
s3:GetObject | 既存オブジェクトの取得(同期時の差分確認) |
s3:ListBucket | バケット内のオブジェクト一覧取得(同期時の差分確認) |
s3:DeleteObject | --deleteフラグによる不要ファイルの削除 |
CodePipelineによるパイプラインの構築
CodeBuildの設定のみでは、CodeCommitへのプッシュを自動的に検知してビルドを実行することはできません。CodeCommitへのプッシュをトリガーとした自動ビルドを実現するために、AWS CodePipelineを使用してCI/CDパイプラインを構築します。
パイプラインの作成
CodePipelineの管理画面からパイプラインを作成します。設定のポイントは以下の通りです。
- パイプラインタイプ: 「カスタムパイプラインを構築する」を選択
- パイプライン名: 一意の名前を指定(例:
codepipeline-xxx-build) - サービスロール: 「新しいサービスロール」を選択
- ソースステージ: CodeCommitを選択し、ビルド対象のリポジトリとブランチを指定
- 変更検出: 「ソースの変更を自動的に検出するEventBridgeルールを作成」にチェックが入っていることを確認
- ビルドステージ: 「その他のビルドプロバイダー」からCodeBuildを選択し、先に作成したビルドプロジェクトを指定
- テストステージ: スキップ
- デプロイステージ: スキップ(S3へのデプロイは
buildspec.ymlのpost_buildで実行するため)
ソースステージの設定で「EventBridgeルールを作成」にチェックを入れると、CodeCommitのリポジトリへのプッシュイベントをAmazon EventBridgeが検知し、自動的にパイプラインを起動します。
パイプラインの作成が完了すると、以下のフローが自動化されます。
CloudFrontによるコンテンツ配信
ディストリビューションの作成
Amazon CloudFrontでディストリビューションを作成し、S3バケットのコンテンツをCDN経由で配信します。
- CloudFrontの管理画面で「ディストリビューションを作成」を選択
- 必要に応じてプランを選択(検証目的であればフリープランで開始可能)
- Distribution name: サイト名など一意の名前を入力
- Distribution type: 「Single website or app」を選択
- ドメイン設定: Route 53でドメインを管理している場合は同時に設定可能(後からの設定も可能)
- Origin type: 「S3」を選択
- S3 origin: 先に作成したS3バケットを指定(「Browse S3」から選択可能)
- その他のオプションは初期値のまま、「Create distribution」まで進めてディストリビューションを作成
Default root objectの設定
ディストリビューションの作成後、管理画面の詳細セクションに「ディストリビューションドメイン名」が表示されます。これがCloudFrontから割り当てられた一時的なURLです。
ただし、初期状態ではルートURL(https://xxxx.cloudfront.net/)でアクセスした際にエラーが返される場合があります。これは、Default root objectが未設定のためです。
以下の手順で設定します。
- ディストリビューションの管理画面で「一般」タブを選択
- 「編集」を選択
- Default root objectの項目に
index.htmlを入力 - 変更を保存
この設定により、https://xxxx.cloudfront.net/へのアクセスが自動的にhttps://xxxx.cloudfront.net/index.htmlとして処理されます。
トラブルシューティング: AccessDeniedエラー
CloudFrontのディストリビューションドメイン名でサイトにアクセスした際に、以下のようなエラーが返される場合があります。
<Error>
<Code>AccessDenied</Code>
<Message>Access Denied</Message>
</Error>
ディストリビューション作成前後でS3バケットのポリシーを手動で変更していない場合、このエラーの主な原因はDefault root objectの未設定です。
ディストリビューション作成時に、CloudFrontはS3バケットに対して必要なアクセスポリシーを自動的にアタッチします。そのため、ポリシーを手動で変更していなければ、権限の問題でこのエラーが発生することは通常ありません。
https://xxxx.cloudfront.net/index.htmlのようにファイル名を明示的に指定してアクセスが成功する場合は、Default root objectにindex.htmlを設定することで解消できます。
まとめ
この記事では、Docusaurusで作成した静的サイトをAmazon S3 + CloudFrontで配信し、CodeCommit、CodePipeline、CodeBuildによるCI/CDパイプラインを構築する手順について解説しました。
この構成により、CodeCommitへのプッシュをトリガーとして、ビルドからS3への配置、CloudFrontでの配信までが自動化されます。AWSエコシステム内でコンテンツ管理から配信までを一貫して運用できる点が、この構成の特徴です。
参考リンク:

