はじめに
個人のポートフォリオページなどを作って公開するとき、サーバ管理に手間をかけたくない。
とはいえ、あまりにもお粗末な環境で配信するのも気が引ける。
AWSのサーバレスサービスで手軽に、かつ "ちゃんとした" 配信環境を整備する手順をまとめる。
サンプルコード↓
サーバレスでウェブサイトを運用するメリット
- サーバ負荷を気にしなくて良い
- SSLサーバ証明書を勝手に更新してくれる
- AWSは言わずもがな堅牢
要するに、最初と更新時だけ気にかけてやれば、あとはAWSに丸投げして放置できる。
やること
- ポートフォリオページなど、静的なウェブサイトを運用する環境をつくる
- 手間は最小限に、"ちゃんとした" 配信環境をつくる(独自ドメイン + https通信)
- AWSのS3、CloudFront、CertificateManagerを使う
前提
- 取得済の独自ドメイン (本ページでは、MuuMuuドメインで契約したもの)
もくじ
- S3 bucketにhtmlファイルを配置する
- CloudFrontとS3を接続する
- CloudFrontと独自ドメインを接続する
- [option] エラー時に返すファイルを設定する
1. S3 bucketにhtmlファイルを配置する
1-1. S3 bucketを新規作成する
S3のコンソールを開いたら、画面右上のCreate bucketをクリック
① 適当なBucket nameを入力する。
② (CloudFrontを介さない) S3への直接アクセスは全て遮断する。
他の項目はご自由に。
画面右下のCreate bucketを押して完了。
1-2. S3 bucketにファイルをアップロードする
作成されたbucketを開いて、Uploadを押す。
① Add files または Add folderでアップロードしたいファイルを選択する。
② Uploadボタンを押す。
必要なファイルが揃うまで、アップロードを繰り返す。
本ページでは、下記のようなファイル構造でS3 bucketのルートディレクトリに配置した。
assets/
├ css/ - default.css
└ img/ - image.png
index.html
これでS3の準備が整った。
2. CloudFrontとS3を接続する
2-1. CloudFront Distributionを新規作成する
CloudFrontのコンソールを開いたら、画面左上のCreate Distributionを押す。
① Origin Domain Nameには、先程新規作成したS3 bucketを設定する。
${作成したbucket名}.s3.amazonaws.com
に名称が一致していることを確認する。
② CloudFrontからのみS3 bucketの中身を参照する権限の設定。
Origin Access Identity
を新規発行して、S3 bucketのポリシーも勝手に書き換えてくれる。
③ http通信もhttps通信として解釈する設定。
④ 手順1-2でS3 bucketに配置したhtmlのファイル名を設定する。
⑤ 全て設定したら、画面右下のCreate Distributuionを押す。
はじめの画面に戻ると、新しいDistributionが一覧に加わっている。
StatusがIn Progress
からDeployed
に変わったら、作成完了。
2-2. CloudFrontからS3 bucketの中身を参照できるか確認する
作成されたDistributionを開いて、ドメイン名を確認する。
確認したドメイン名をブラウザにコピペして、S3 bucketに配置したhtmlを参照できればok。
ファイルをS3 bucketに正しく配置できていれば、cssや画像も読める。
これでCloudFrontとS3を接続できた。
3. CloudFrontと独自ドメインを接続する
本ページではMuuMuuドメインで契約したuni-ezobafun.com
をCloudFrontに紐付ける。
3-1. Certificate Managerで証明書発行をリクエストする
手順2-2と同じ画面で、左上にあるEditを押して、Distribution Settings
を開く。
画面中央のRequest or Import a Certificate with ACM
を押す。
画面の案内に従って、Domain nameは*.${設定する独自ドメイン}
、Validation methodはDNS
を設定する。
正しく設定するとReview画面に進むので、内容を確認したらConfirm and request
を押す。
証明書の一覧ページからリクエストしたドメインの情報を開き、NameとValueをコピーしておく。
3-2. MuuMuuドメインに認証情報を登録する
画面左のムームーDNS
を押す。
CloudFrontに紐付けるドメインの変更(利用する)
を押す。
ここでは2行追加する。
種別はいずれもCNAMEを選択する
1行目では、手順3-1でコピーしておいたNameをサブドメイン欄に、Valueを内容欄にペーストする。
このとき下記の[ ]で示した部分 (2箇所) は省いてペーストする。
name
_4c450f3c7930a5e76f5573d74a67fb2c[.uni-ezobafun.com.]
value
_0c7f35b87c9dcb9ac0a7d3df240fc2b1.vtqfhvjlcp.acm-validations.aws[.]
2行目では、任意の文字列をサブドメイン欄に、手順2-2で確認したCloudFrontのドメイン名を内容欄にペーストする。
セットアップ情報変更
を押して、変更を反映する。
3-3. 証明書が発行されたことを確認する
しばらく待ってから右上の更新ボタンを押すと、StatusがIssued
に変わる。
3-4. 発行された証明書を使って、CloudFrontに独自ドメインを接続する
手順3-1と同様にDistribution Settings
を開く。
CloudFrontに接続するドメイン名(手順3-2で設定したサブドメインを先頭に付与したもの)をAlternate Domain Names
に設定する。
SSL Certificate
はCustom SSL Certificate
とし、手順3-3で発行した証明書を選択する。
画面右下のYes, Edit
を押すと、DistributionのStatusが再びIn Progress
になるため、Deployed
になるまで待つ。
設定したドメイン名をブラウザにコピペして、S3 bucketに配置したhtmlを参照できればok。
これでCloudFrontと独自ドメインを接続できた。
4. [option] エラー時に返すファイルを設定する
4-1. エラー時に返すファイルをS3 bucketにアップロードする
error.htmlをS3 bucketのルートディレクトリに配置する。
assets/
├ css/ - default.css
└ img/ - image.png
index.html
error.html
4-2. CloudFrontでエラー時に返すファイルを指定する
Distributionを開いて、Error Pages
タブから、Create Custom Error Response
を押す。
下記は内部で403エラーだった時、一律でerror.htmlを返し、404エラーとしてレスポンスする例。
その他、好みの組み合わせにて。
トラブルシュート
S3のファイルを更新しても変更が反映されない
まずはブラウザのキャッシュをクリアしてみる。
それでも変更が反映されなければ、CloudFrontのキャッシュをクリアする。
エラーページでcssや画像を読み込めない
cssファイルや画像ファイルの参照先を相対パスで指定していると、エラーページから読み込めない。
error.htmlを配置したパスではなく、リクエストされたパスを起点にして参照してしまうのが原因。
ルートパスで参照先を指定すれば解決する。
リクエストURLからindex.htmlを省略できない
手順3-4では、https://welcome.uni-ezobafun.com
の末尾で/index.html
を指定しなくても、暗黙的にS3 bucketのルートディレクトリに配置したindex.htmlを参照できた。
ルートディレクトリ以外に配置した他のファイルも/index.html
を省略したリクエストURLで参照したいところだが、結論から言うと本ページの方法では実現できない。
手順2-1で設定したCloudFrontのDefault Root Object
が、各Originのルートディレクトリ以外には適用されないのが原因。
解決策としては、参照するページごとに別のS3 bucketを作成するか、S3のStatic website hosting
を使うことになる。
前者はファイル管理が面倒そうな点、後者はCloudFrontを通さない通信を許容してしまう点がデメリット。
参考
公式ドキュメント
https://aws.amazon.com/premiumsupport/knowledge-center/cloudfront-serve-static-website/
https://docs.aws.amazon.com/AmazonS3/latest/dev/WebsiteEndpoints.html#WebsiteRestEndpointDiff