AWS CloudFrontとS3を使用した静的サイト構築
概要
s3、cloudfrontを使用してサーバーを立てずに静的サイトを運用するための設定になります。
バックエンドと絡むシステムでもフロント部分だけをCloudFrontとS3で運用することもできます。
また、CloudFrontは非常に高性能ですので、アクセスが集中しても、よっぽどでない限り制限緩和を申請せずとも問題なく運用できます。
CloudFrontの制限値に関しては以下がわかりやすいです。
料金
CloudFrontの料金は下記をご参照ください。(S3は省きます)
サーバー立てるよりかなり安いと思います。
1. S3にバケットを作成
S3のコンソールからバケットを作成ボタンをクリックし、
バケット名を記載して作成する。
デフォルトでパブリックアクセスを全てブロックになっているため、
他はそのままで大丈夫です。

2. CloudFrontにDistributionを作成
CloudFrontのコンソールからCreate Distributionボタンをクリックする。
オリジンドメインに1で作成したバケットを選択、
S3バケットアクセスでOrigin access control settingsにチェック、
コントロール設定を作成ボタンでOrigin access controlを作成、

ビューワープロトコルポリシーでRedirect HTTP to HTTPSにチェックを入れる。

デフォルトルートオブジェクトにindex.htmlと入力し、
ディストリビューションを作成ボタンをクリックし作成する。
テスト用の場合は付与されるドメイン(xxxxxxx.cloudfront.netみたいな)を使用すればいいですが、
本番用の場合で任意のドメインを使用したい場合は、事前にAWS Certificate Managerで証明書を作成しておき、代替ドメイン名を追加し、
カスタムSSL証明書で作成した証明書を選択してください。
DNSを登録すれば、任意のドメインでアクセスできるようになります。

3. S3のバケットポリシーを編集
1で作成したバケットのアセクス許可タブでバケットポリシーを編集します。
CloudFrontのarnは、作成したCloudFrontの一般タブで確認していただけます。

{
"Version": "2008-10-17",
"Statement": [
{
"Sid": "AllowCloudFrontServicePrincipalReadOnly",
"Effect": "Allow",
"Principal": {
"Service": "cloudfront.amazonaws.com"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::バケット名/*",
"Condition": {
"StringEquals": {
"AWS:SourceArn": "CloudFrontのarn"
}
}
}
]
}
4. ドメイン確認
作成したDistributionの一般タブでドメインを確認できますので、
バケットにindex.htmlを保存すれば、このドメインでindex.htmlをブラウザで閲覧することができます。

5. 注意事項
・サブディレクトリのindex.htmlへのアクセス
index.htmlへパスでアクセスしたい場合があると思いますが、
(例えば、/hoge/index.htmlへ、https://exmaple.com/hoge でアクセスする)
CloudFrontではサブディレクトリのindex.htmlへはフルパス(https://exmaple.com/hoge/index.html) を指定しないとアクセスできません。
サブディレクトリのindex.htmlへパスでアクセスしたい場合は、別で手順を作成していますので、以下の手順を参照してください
・Basic認証の追加
Basic認証の追加は別で手順を作成していますので、以下の手順を参照してください
・S3 バケットを us-east-1 以外のリージョンで作成した場合
バケットを作成してから 数十分〜2時間くらい経たないと、正常に動作しないことがあります。
S3バケットを作成後、バケット名がすべてのAWSリージョンに伝達されるまで最大24時間かかることがあり、
その間に同じリージョンにないリージョンのエンドポイントにリクエストすると「307 Temporary Redirect」レスポンスが返り、S3の場合はS3のデフォルトエンドポイント (s3.amazonaws.com) に転送され、そこから正しいオブジェクトURLに転送されます。
・htaccessは使えません
htaccessは使えませんが、CloudFrontFunctionを使用したりして、特定パスのリダイレクトであったり、特定のパスは別のバケットを使用したりで、補えます。
Discussion