AWS S3 に静的ウェブサイトをホスティングして独自ドメインで公開するまで

この記事は個人ブログと同じ内容です

www.ritolab.com


静的ウェブサイトを Amazon S3ホスティングし、独自ドメインで公開するまでの環境構築を terraform を使って行っていきます。

実行環境

今回の実行環境は以下になります

  • Terraform v0.15.1

コードはモジュール化を行わずに一つの tf ファイルに書いていきます。

今回使う AWS のサービスは、S3 と Route53 です。

環境変数について

terraform で構成を定義していくにあたり、環境変数を tfvars に記述しておきますが、以下のようになっています。

terraform.tfvars

aws_id           = 123456789
aws_access_key   = "XXXXXXXXXXXXXXXXXXXX"
aws_secret_key   = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
aws_region       = "ap-northeast-1"
domain_name      = "example.com"
domain_host_name = "www"
  • AWS のアカウント情報と、デフォルトのリージョンとして東京リージョンを指定しています。
  • ネイキッドドメインとホスト名をそれぞれ分けて定義しています。

変数の設定

これから使用する値について変数とプロバイダを設定しておきます。

main.tf

# variables
variable "aws_id" {}
variable "aws_access_key" {}
variable "aws_secret_key" {}
variable "aws_region" {}
variable "domain_name" {}
variable "domain_host_name" {}

provider "aws" {
  access_key = var.aws_access_key
  secret_key = var.aws_secret_key
  region     = var.aws_region
}

locals {
  fqdn = {
    name = "${var.domain_host_name}.${var.domain_name}"
  }
  bucket = {
    name = local.fqdn.name
  }
}
  • AWS プロバイダを定義しています。
  • Route53 や S3 で使用するための FQDNBucket 名の変数を作成しています。

アクセスログ用のバケット作成

S3 にホスティングする場合でも、アクセスログを取る事ができます。

docs.aws.amazon.com

そのためのバケットを S3 に作成します。(これが無くてもサイト公開はできるので、必要なら作成してください)

main.tf

## AWS アカウントのユーザー
data "aws_canonical_user_id" "current_user" {}

## S3 for app logs
resource "aws_s3_bucket" "app_logs" {
  bucket = "${local.bucket.name}-logs"

  grant {
    id          = data.aws_canonical_user_id.current_user.id
    permissions = ["FULL_CONTROL"]
    type        = "CanonicalUser"
  }
  grant {
    permissions = ["READ_ACP", "WRITE"]
    type        = "Group"
    uri         = "http://acs.amazonaws.com/groups/s3/LogDelivery"
  }
}
  • 権限は ACL ポリシーで設定しています。
    • 前者(1 つめの grant)は、コンソール画面から操作できるように、AWS アカウントの正規ユーザーの権限を設定しています。
    • 後者(2 つめの grant)は、ログを配信するための権限です。

アプリケーション用のバケット作成

静的なウェブサイトのソースコードを配置する S3 バケットを作成します。

main.tf

## S3 for Static Website Hosting
resource "aws_s3_bucket" "app" {
  bucket = local.bucket.name
  acl    = "public-read"
  policy = templatefile("bucket-policy.json", {
    "bucket_name" = local.bucket.name
  })

  website {
    index_document = "index.html"
    error_document = "error.html"
  }

  logging {
    target_bucket = aws_s3_bucket.app_logs.id
    target_prefix = "log/"
  }
}

バケット名は FQDN と同じにします。

templatefile として挿入している json は以下のようになっています。

bucket-policy.json

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": [
                "s3:GetObject"
            ],
            "Resource": [
                "arn:aws:s3:::${bucket_name}/*"
            ]
        }
    ]
}

logging の部分は、前項でアクセスログ用のバケットを作成した場合に指定するので、作っていなければ指定不要です。

バケットを作成したら index.html を配置してアクセスしてみると表示されます。

f:id:ro9rito:20210507113705p:plain

独自ドメインの設定

WEB サイトの公開はできましたが、ここまでだと URL が amazonaws.com なので、独自ドメインを設定します。

ドメインとホストゾーンの作成について

ドメインですが、前提として、Route53 に登録済みのドメインを使用します。

また、ネイキッドドメインのホストゾーン登録は済ませてある前提で進めるので、例えば www.example.com で S3 にホスティングしたサイトを公開するなら、そのネイキッドドメインである example.com のホストゾーンは作成しておいてくだださい。

docs.aws.amazon.com

これだけです。

ちなみに、ドメインのネームサーバーと、作成したホストゾーンの NS レコードに設定されているネームサーバーが同じ事を確認して、もし違うようならどちらかに揃える必要があります。

レコードの設定

terraform で Route53 にレコードを作成します。

main.tf

# Route 53
## ネイキッドドメインのホストゾーン情報
data aws_route53_zone "naked" {
  name = var.domain_name
}

## A レコード作成(to S3 Bucket)
resource "aws_route53_record" "main_a" {
  zone_id = data.aws_route53_zone.naked.zone_id
  name    = local.fqdn.name
  type    = "A"
  alias {
    evaluate_target_health = true
    name = "s3-website-${var.aws_region}.amazonaws.com"
    zone_id = aws_s3_bucket.app.hosted_zone_id
  }
}
  • A レコードを作成しています。
  • ホストゾーンは、作成済みのネイキッドドメインのホストゾーン情報を取得して zone_id に指定しています。
  • エイリアスの設定として、S3 のウェブサイトエンドポイントを設定します。

docs.aws.amazon.com

動作確認

レコードを作成したら、あとは DNS の浸透を待ってアクセスすると表示されます。

f:id:ro9rito:20210507113920p:plain

S3 にホスティングしたウェブサイトを独自ドメインで公開できました。