コーポレートサイトやドキュメントサイトなどの静的コンテンツは、S3 + CloudFrontで配信するのが最もコスト効率が良い方法です。EC2やECSを使う必要がなく、サーバー管理も不要。この記事ではACM証明書によるHTTPS化まで含めた構築手順を解説します。
目次
アーキテクチャ概要
構成はシンプルで、ユーザー → CloudFront → S3(OAC経由)という流れです。S3バケットはパブリックアクセスを完全にブロックし、CloudFrontからのみアクセスを許可します。OAC(Origin Access Control)を使うことで、S3の静的ウェブサイトホスティング機能を使わずに安全に配信できます。
S3バケットの設定
resource "aws_s3_bucket" "site" {
bucket = "my-static-site-bucket"
}
resource "aws_s3_bucket_public_access_block" "site" {
bucket = aws_s3_bucket.site.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
resource "aws_s3_bucket_policy" "site" {
bucket = aws_s3_bucket.site.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Sid = "AllowCloudFrontOAC"
Effect = "Allow"
Principal = { Service = "cloudfront.amazonaws.com" }
Action = "s3:GetObject"
Resource = "${aws_s3_bucket.site.arn}/*"
Condition = {
StringEquals = {
"AWS:SourceArn" = aws_cloudfront_distribution.site.arn
}
}
}
]
})
}
CloudFrontディストリビューションの設定
ポイントはOACの設定とデフォルトルートオブジェクトの指定です。SPAの場合はカスタムエラーレスポンスで404を /index.html にリダイレクトする設定も必要です。
resource "aws_cloudfront_distribution" "site" {
origin {
domain_name = aws_s3_bucket.site.bucket_regional_domain_name
origin_id = "S3Origin"
origin_access_control_id = aws_cloudfront_origin_access_control.site.id
}
enabled = true
default_root_object = "index.html"
default_cache_behavior {
allowed_methods = ["GET", "HEAD"]
cached_methods = ["GET", "HEAD"]
target_origin_id = "S3Origin"
viewer_protocol_policy = "redirect-to-https"
forwarded_values {
query_string = false
cookies { forward = "none" }
}
min_ttl = 0
default_ttl = 86400
max_ttl = 31536000
compress = true
}
viewer_certificate {
acm_certificate_arn = aws_acm_certificate.site.arn
ssl_support_method = "sni-only"
minimum_protocol_version = "TLSv1.2_2021"
}
restrictions {
geo_restriction { restriction_type = "none" }
}
}
デプロイの自動化
GitHub Actionsを使えば、mainブランチへのpush時に自動でS3にアップロードし、CloudFrontのキャッシュを無効化できます。
# .github/workflows/deploy.yml
name: Deploy to S3
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Sync to S3
run: aws s3 sync ./dist s3://my-static-site-bucket --delete
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_REGION: ap-northeast-1
- name: Invalidate CloudFront
run: |
aws cloudfront create-invalidation \
--distribution-id ${{ secrets.CF_DISTRIBUTION_ID }} \
--paths "/*"
まとめ
S3 + CloudFrontは静的サイトのホスティングにおいて、コスト・パフォーマンス・セキュリティのすべてで優れた選択肢です。月間100万PV程度のサイトでも月額数百円で運用できるため、EC2で静的サイトを配信している場合は移行を検討する価値があります。

コメント