今回やること
Terraformを使用して、以下のインフラを構築し、Reactアプリケーションをホスティングする環境を作ります。
- S3: Reactアプリケーションをホストする静的ウェブサーバー。
- CloudFront: コンテンツ配信を最適化し、セキュリティと高速化を提供。
S3とは?
S3 (Simple Storage Service) は、AWSが提供するオブジェクトストレージサービスです。以下の特徴を持っています:
- 静的ウェブホスティングが可能(HTML、CSS、JavaScriptなどを公開)。
- 高い耐久性と可用性を備えたデータ保存。
- アクセス管理が柔軟で、CloudFrontとの連携も容易。

AWS S3によるファイルストレージの設定【エンジニア初心者向けガイド】
AWS S3バケット作成からファイルアップロード、アクセス管理、バージョニングまで、エンジニア初心者向けにわかりやすく解説します。
CloudFrontとは?
CloudFrontは、AWSのCDN(Content Delivery Network)サービスです。以下のメリットがあります:
- 低遅延: グローバルなエッジロケーションを利用して、ユーザーに近い場所からデータを配信。
- セキュリティ: DDoS攻撃から保護し、HTTPSによる暗号化通信をサポート。
- S3と統合: S3バケットからコンテンツを安全かつ効率的に配信。

初心者エンジニア向け CloudFrontによるコンテンツ配信とセキュリティ概要
AWS CloudFrontでのコンテンツ配信を最適化し、SSL/TLS証明書によるセキュリティを強化する設定方法を解説。キャッシュ管理やオリジン設定も詳しく紹介します。
Reactの環境構築
Reactアプリのセットアップ
下記記事を参考にセットアップしてください。

Viteを使ってReactプロジェクトを作成する方法
Viteを使ってReactプロジェクトを手軽に構築する方法を解説。初期設定や生成されたファイル構成についても詳しく説明しています。
ビルドファイルの作成
下記コマンドを実行してビルドファイルの生成です。
Bash
npm run build
build/
フォルダにHTML、CSS、JavaScriptなどの静的ファイルが出力されます。
GithubActionsの設定
mainにpushした場合にs3にアップロードするようにしています。
事前に下記シークレットキーを登録してください。
- AWS_ACCESS_KEY_ID
- AWS_SECRET_ACCESS_KEY
- S3_BUCKET_NAME
YAML
name: Deploy to S3
on:
push:
branches:
- main
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
# 1. リポジトリのチェックアウト
- name: Checkout repository
uses: actions/checkout@v3
# 2. Node.jsのセットアップ
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: 16
# 3. パッケージのインストールとビルド
- name: Install dependencies and build
run: |
npm install
npm run build
# 4. AWS CLIの設定
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v3
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ap-northeast-1
# 5. S3へのファイル同期
- name: Sync files to S3
run: |
aws s3 sync ./dist s3://${{ secrets.S3_BUCKET_NAME }} --delete
S3の環境構築
ここでは、Terraformを使用してAWS S3バケットを作成し、Reactアプリケーションの静的ファイルをホストする環境を構築します。
流れは下記です。
- S3バケットの作成
- Reactアプリの静的ファイルをホストするためのバケットを作成。
- バケットに適切なタグを付与し、環境ごとに識別可能に。
- パブリックアクセスの設定
- 一般的なパブリックアクセス制御を無効化し、CloudFront経由での安全なアクセスを確保。
- バケットポリシーの適用
- CloudFrontからのアクセスのみ許可するセキュリティポリシーを設定。
S3バケットの作成
HCL
resource "aws_s3_bucket" "sample_bucket" {
bucket = var.bucket_name
tags = {
Name = "${var.project}-bucket"
Environment = var.environment
}
}
resource "aws_s3_bucket" "sample_bucket"
:aws_s3_bucket
は、TerraformでS3バケットを作成するためのリソースタイプです。"sample_bucket"
は、このリソースをTerraform内で識別するための一意の名前です。
bucket = var.bucket_name
:- S3バケットの名前を指定します。
- バケット名はTerraformの変数(
var.bucket_name
)から取得します。 - バケット名はグローバルで一意である必要があります(例:
my-unique-bucket-name
)。
tags
:- バケットにタグを付与します。
- タグはAWSリソースを識別しやすくするために利用され、運用時に非常に便利です。
Name
: バケットの名前(プロジェクト名に基づいて設定)。Environment
: 環境の種類(例: 開発、ステージング、本番)。
ブロックパブリックアクセスの無効化
HCL
resource "aws_s3_bucket_public_access_block" "sample_bucket_public_access" {
bucket = aws_s3_bucket.sample_bucket.id
block_public_acls = false
block_public_policy = false
ignore_public_acls = false
restrict_public_buckets = false
}
aws_s3_bucket_public_access_block
:- このリソースは、S3バケットのパブリックアクセスを制御する設定を定義します。
bucket = aws_s3_bucket.sample_bucket.id
:- この設定が適用されるS3バケットを指定します。ここでは、上記で作成した
sample_bucket
のIDを使用します。
- この設定が適用されるS3バケットを指定します。ここでは、上記で作成した
- パブリックアクセスの設定:
block_public_acls
: バケットのパブリックACLをブロックするかどうか。block_public_policy
: パブリックポリシーをブロックするかどうか。ignore_public_acls
: パブリックACLを無視するかどうか。restrict_public_buckets
: バケットをパブリックアクセスから制限するかどうか。- ここでは、すべての設定を
false
にしてパブリックアクセスを許可しています。CloudFront経由でのアクセスに依存するため、後述のバケットポリシーでセキュリティを強化します。
S3バケットポリシーの設定
HCL
resource "aws_s3_bucket_policy" "sample_bucket_policy" {
bucket = aws_s3_bucket.sample_bucket.id
policy = jsonencode({
Version = "2012-10-17",
Statement = [
{
Effect = "Allow",
Principal = {
"Service" : "cloudfront.amazonaws.com"
},
Action : "s3:GetObject",
Resource : "${aws_s3_bucket.sample_bucket.arn}/*",
Condition : {
StringEquals : {
"AWS:SourceArn" : "${aws_cloudfront_distribution.sample_cdn.arn}"
}
}
}
]
})
}
aws_s3_bucket_policy
:- S3バケットに適用するポリシー(アクセス制御のルール)を定義します。
bucket = aws_s3_bucket.sample_bucket.id
:- ポリシーを適用するS3バケットを指定します。
policy = jsonencode({...})
:- JSON形式でポリシーを記述し、それをTerraformで適用可能な形式にエンコードします。
- ポリシーの内容:
Effect
: 許可する動作を指定します。Allow
で動作を許可。Principal
: アクセスを許可する主体を指定します。ここではcloudfront.amazonaws.com
(CloudFrontサービス)を指定。Action
: 許可するアクション。ここでは、s3:GetObject
(オブジェクトの取得)を許可。Resource
: このポリシーが適用されるリソース。バケット内のすべてのオブジェクト(/*
)を指定。Condition
:- CloudFront経由のアクセスのみ許可する条件を指定。
AWS:SourceArn
: CloudFrontディストリビューションのARNを指定。
(後ほど設定します。)
CloudFrontの環境構築
以下では、CloudFrontに関連するTerraformコードの各部分を解説します。
CloudFront Origin Access Control (OAC)
OACは、AWS CloudFrontがバックエンドのオリジン(例: S3バケット)に安全にアクセスできるようにする仕組みです。
HCL
resource "aws_cloudfront_origin_access_control" "sample_oac" {
name = "sample-oac"
origin_access_control_origin_type = "s3"
signing_behavior = "always"
signing_protocol = "sigv4"
}
aws_cloudfront_origin_access_control
:- CloudFrontとS3バケットを連携させる際に使用する「Origin Access Control(OAC)」を作成します。
- OACは、CloudFrontがS3バケットに安全にアクセスできるようにするための設定です。
- 各属性の説明:
name
:- OACの名前です。分かりやすい名前を付けてください(例:
"sample-oac"
)。
- OACの名前です。分かりやすい名前を付けてください(例:
origin_access_control_origin_type
:- オリジンの種類を指定します。ここでは、CloudFrontがアクセスする先がS3であるため、
"s3"
を指定します。
- オリジンの種類を指定します。ここでは、CloudFrontがアクセスする先がS3であるため、
signing_behavior
:- すべてのリクエストに署名を付ける設定。
"always"
で常に署名付きリクエストを使用します。
- すべてのリクエストに署名を付ける設定。
signing_protocol
:- S3とやり取りする際の署名プロトコル。最新かつ推奨される
"sigv4"
を指定します。
- S3とやり取りする際の署名プロトコル。最新かつ推奨される
CloudFrontディストリビューションの設定
主に下記内容を設定しています。
- origin(オリジン設定)
- default_cache_behavior(キャッシュ設定)
- viewer_certificate(SSL証明書設定)
- restrictions(地域制限)
- default_root_object
- custom_error_response(カスタムエラーレスポンス)
- tags(リソースタグ)
HCL
resource "aws_cloudfront_distribution" "sample_cdn" {
origin {
domain_name = aws_s3_bucket.sample_bucket.bucket_regional_domain_name
origin_id = "S3-${var.bucket_name}"
origin_access_control_id = aws_cloudfront_origin_access_control.sample_oac.id
}
enabled = true
default_cache_behavior {
allowed_methods = ["GET", "HEAD"]
cached_methods = ["GET", "HEAD"]
target_origin_id = "S3-${var.bucket_name}"
viewer_protocol_policy = "redirect-to-https"
forwarded_values {
query_string = true
cookies {
forward = "all"
}
}
}
viewer_certificate {
cloudfront_default_certificate = true
}
restrictions {
geo_restriction {
restriction_type = "whitelist"
locations = ["JP"]
}
}
default_root_object = "index.html"
custom_error_response {
error_code = 403
response_code = 200
response_page_path = "/index.html"
}
custom_error_response {
error_code = 404
response_code = 200
response_page_path = "/index.html"
}
tags = {
Name = "${var.project}-cdn"
Environment = var.environment
}
}
origin
- 役割: CloudFrontがコンテンツを取得するオリジン(S3バケット)を指定します。
- 各属性の説明:
domain_name
:- オリジンとなるS3バケットのドメイン名を指定します。ここでは
aws_s3_bucket.sample_bucket.bucket_regional_domain_name
を使用し、バケットのリージョンに基づいたドメイン名を設定。
- オリジンとなるS3バケットのドメイン名を指定します。ここでは
origin_id
:- このオリジンを識別する一意のIDを指定します(例:
"S3-${var.bucket_name}"
)。
- このオリジンを識別する一意のIDを指定します(例:
origin_access_control_id
:- 作成したOACのIDを指定し、CloudFrontがS3に安全にアクセスできるようにします。
default_cache_behavior
- 役割: CloudFrontがキャッシュやHTTPリクエストをどのように処理するかを定義します。
- 各属性の説明:
allowed_methods
:- CloudFrontが許可するHTTPメソッドを指定します(例:
["GET", "HEAD"]
)。 - 静的サイトでは、GETとHEADのみで十分です。
- CloudFrontが許可するHTTPメソッドを指定します(例:
cached_methods
:- キャッシュされるHTTPメソッドを指定します(例:
["GET", "HEAD"]
)。
- キャッシュされるHTTPメソッドを指定します(例:
target_origin_id
:- キャッシュのターゲットとなるオリジンIDを指定。
origin
ブロックで設定したIDと一致させます。
- キャッシュのターゲットとなるオリジンIDを指定。
viewer_protocol_policy
:- クライアントがHTTPでリクエストした場合の動作を定義。
"redirect-to-https"
を指定すると、HTTPリクエストをHTTPSにリダイレクトします。
forwarded_values
:- CloudFrontがリクエスト時にオリジンに転送するデータの設定。
query_string
:- クエリパラメータをS3に転送するかどうか。
cookies
:- クッキー情報を転送するかどうか(
"all"
で全て転送)。
- クッキー情報を転送するかどうか(
viewer_certificate
- 役割: CloudFrontで使用するSSL証明書を設定します。
cloudfront_default_certificate
:- デフォルトのCloudFront提供のSSL証明書を使用(HTTPS通信が可能)
restrictions
- 役割: コンテンツを配信する地域を制限します。
geo_restriction
:restriction_type
:- 地域制限の種類を指定。ここでは
"whitelist"
を指定し、日本のみ許可。
- 地域制限の種類を指定。ここでは
locations
:- 配信を許可する地域の国コード(例:
"JP"
)
- 配信を許可する地域の国コード(例:
default_root_object
- 役割: リクエストのURLにファイル名が含まれない場合に表示されるデフォルトファイルを指定します。
- 例:
"index.html"
custom_error_response
- 役割: 特定のHTTPエラーコード(403, 404など)を処理し、カスタムページを返します。
- 各属性の説明:
error_code
:- エラーコード(例:
403
)。
- エラーコード(例:
response_code
:- クライアントに返すHTTPレスポンスコード(例:
200
)。
- クライアントに返すHTTPレスポンスコード(例:
response_page_path
:- エラー時に表示するページのパス(例:
/index.html
)。
- エラー時に表示するページのパス(例:
Terraformの変数ファイル設定
variables.tfの内容
HCL
variable "project" {
type = string
default = "sample-infra"
}
variable "region" {
type = string
default = "ap-northeast-1"
}
variable "environment" {
type = string
default = "production"
}
variable "bucket_name" {
type = string
default = "sample-infra-deploy"
}
今回作成したコード全文
今回作成したmain.tfです。
1ファイルに全てのリソースを記述すると、可読性が悪くなるので、適宜ファイル分割をしてください。
HCL
# 変数
variable "project" {
type = string
default = "sample-infra"
}
variable "region" {
type = string
default = "ap-northeast-1"
}
variable "environment" {
type = string
default = "production"
}
variable "bucket_name" {
type = string
default = "sample-infra-deploy"
}
provider "aws" {
region = var.region
}
# oac
resource "aws_cloudfront_origin_access_control" "sample_oac" {
name = "sample-oac"
origin_access_control_origin_type = "s3"
signing_behavior = "always"
signing_protocol = "sigv4"
}
# ディストリビューション
resource "aws_cloudfront_distribution" "sample_cdn" {
origin {
domain_name = aws_s3_bucket.sample_bucket.bucket_regional_domain_name
origin_id = "S3-${var.bucket_name}"
origin_access_control_id = aws_cloudfront_origin_access_control.sample_oac.id
}
enabled = true
default_cache_behavior {
allowed_methods = ["GET", "HEAD"]
cached_methods = ["GET", "HEAD"]
target_origin_id = "S3-${var.bucket_name}"
viewer_protocol_policy = "redirect-to-https"
forwarded_values {
query_string = true
cookies {
forward = "all"
}
}
}
viewer_certificate {
cloudfront_default_certificate = true
}
restrictions {
geo_restriction {
restriction_type = "whitelist"
locations = ["JP"]
}
}
default_root_object = "index.html"
custom_error_response {
error_code = 403
response_code = 200
response_page_path = "/index.html"
}
custom_error_response {
error_code = 404
response_code = 200
response_page_path = "/index.html"
}
tags = {
Name = "${var.project}-cdn"
Environment = var.environment
}
}
# s3リソース
resource "aws_s3_bucket" "sample_bucket" {
bucket = var.bucket_name
tags = {
Name = "${var.project}-bucket"
Environment = var.environment
}
}
resource "aws_s3_bucket_public_access_block" "sample_bucket_public_access" {
bucket = aws_s3_bucket.sample_bucket.id
block_public_acls = false
block_public_policy = false
ignore_public_acls = false
restrict_public_buckets = false
}
# バケットポリシー
resource "aws_s3_bucket_policy" "sample_bucket_policy" {
bucket = aws_s3_bucket.sample_bucket.id
policy = jsonencode({
Version = "2012-10-17",
Statement = [
{
Effect = "Allow",
Principal = {
"Service" : "cloudfront.amazonaws.com"
},
Action : "s3:GetObject",
Resource : "${aws_s3_bucket.sample_bucket.arn}/*",
Condition : {
StringEquals : {
"AWS:SourceArn" : "${aws_cloudfront_distribution.sample_cdn.arn}"
}
}
}
]
})
}
Terraformの実行手順
- 初期化
terraform init
- Terraformを初期化し、必要なプラグインをダウンロードします。
- 計画の確認
terraform plan
- 作成予定のリソースを確認します。
- インフラの適用
terraform apply
- 実際にインフラを構築します。
- Reactアプリのデプロイ
build/
フォルダ内のファイルをS3バケットにアップロードします。- AWS CLIやS3の管理画面でアップロード可能です。
まとめ
Terraformを使ったReactアプリのデプロイ環境構築は、S3とCloudFrontの組み合わせで簡単に実現できます。本記事で紹介したコードをカスタマイズし、自身のプロジェクトに適用してみましょう!
コメント