カテゴリー
サブドメイン付きURLで静的なWebサイトをAWS S3/CloudFront(とCloudFront Functions)/Route53で作成する
※ 当ページには【広告/PR】を含む場合があります。
2021/03/10
2022/02/03
ウェブサイトのお引越しは管理者にとっても大変な作業です。
個々数年利用可能になったCloudFrontの軽量サービス版である
さて、サブドメイン付きのURLでのパターンはネット検索しても技術記事の少なさそうな感じがしましたので、ここでまとめておきます。
サブドメイン付きのウェブサイト?
複合的な業態をもつ企業などが自社のウェブサイトの運用に採用している場合がほとんどです。
例えばYahoo社が有名で
www.yahoo.co.jp(メインのドメイン)
travel.yahoo.co.jp
finance.yahoo.co.jp
weather.yahoo.co.jp
auctions.yahoo.co.jp
shopping.yahoo.co.jp
....
というふうに細分化されております。
これは全てyahoo.co.jpというドメイン名の派生ブランチであるサブドメインを利用したもので、もし
yahoo.co.jp
いわゆるサブドメインで区分けされたウェブサイトはその企業や組織のブランド力がものを言いますので、良いイメージが付けばユーザーからアクセスして頂きやすいメリットもあります。
反面、デメリットはどこかブランドの一部で悪いイメージが付いてしまうと、全てのサブドメインの評価を下げてしまう諸刃の剣のようなこともあるようですので、万人にあまり良い印象を与えないテーマのウェブサイトを運用したい場合には別ドメインを利用する方が良いでしょう。
以降の節では、
【通常CloudFront版・作業①】S3でHtmlファイル等を準備
ここからは実際の作業です。
まずは
バケットの作成
まずは静的なウェブサイトホスティングでは、サブドメイン付きのURLと同じ名前をもつS3バケットを新規作成する必要があります。
今回は弊社の保有しているドメイン名に、サブドメインを付けてた以下のURLにウェブサイトを作成してみます。
geek.tacoskingdom.com

S3のリージョンはお好みで選択できますが、弊社は西日本ですのでなんとく最近出来た大阪リージョンを選んでみました。
バケット名の他はデフォルト値で
[バケットを作成]

S3からのウェブサイトホスティングを試すだけの以下のようなステータスコード404用の
index.html
<!doctype html>
<html lang="jp">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="Content-Style-Type" content="text/css; charset=UTF-8">
<meta http-equiv="Content-Script-Type" content="text/javascript; charset=UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<h1>404 not found</h1>
</body>
</html>

ポリシーの付与
このバケットからindex.htmlを公開するのですが、先にアクセス用のポリシーを付与して読み取り専用にしてみます。
まずこのバケットを選んで、
[アクセス許可]
ブロックパブリックアクセス(バケット設定)

次に
バケットポリシー
s3:GetObject
※ご自身のバケット使う場合にはそのバケットの
ARN値
geek.tacoskingdom.com
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Public Policy #1",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::geek.tacoskingdom.com/*"
}
]
}
これでひとまずはS3での作業はOKです。
【通常CloudFront版・作業②】CloudFrontを設定する
次はCloudFrontダッシュボードから作業します。
なお、サブドメインも含めたhttps付きのURLでアクセスしたい場合には、以前説明した
ここでは既に
AWS Certificate Manager
まずは新しいCFディストリビューションを作成します。

上の図では
Create Distribution
ご自身のドメインで試される場合には
geek.tacoskingdom.com
地味な設定で、
Default Root Object
index.html
設定できたら下部の
[Create Distribution]
CloudFrontのダッシュボードトップに戻ると、先程新規作成したディストリビューションが
in Progress

S3バケットポリシーの修正
上のCFの設定で、
Grant Read Permissions on Bucket
Yes, Update Bucket Policy
Sid:2
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Public Policy #1",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::geek.tacoskingdom.com/*"
},
{
"Sid": "2",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity *******"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::geek.tacoskingdom.com/*"
}
]
}
S3のバケットポリシーのPrincipalターゲットを不特定多数('
CloudFront Origin Access Identity <ID値>
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Public Policy #1",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity ***************"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::geek.tacoskingdom.com/*"
}
]
}
なおこの時点で、新規作成したCloudFlontディストリビューションのURLにアクセスしてみると、

ちゃんとS3バケット側をホスティングしてくれているようです。
【通常CloudFront版・作業③】Route53の設定する
では最後に
Route53
ホストゾーンから取得しているドメインを選択し、新規のレコードを作成します。
作成するレコードの設定として、
レコード名:
<サブドメイン名>.ドメイン
レコードタイプ:
A
エイリアス:
はい
エイリアス先:
CloudFrontディストリビューション
> どこかのリージョン
> 先程設定したCFデストリビューションのURL

ではいよいよ
https://geek.tacoskingdom.com

なお、正しく
S3/CloudFront/Route53
https://geek.tacoskingdom.com.s3.ap-northeast-3.amazonaws.com/index.html
https://geek.tacoskingdom.com
これはS3バケットのエンドポイントとCloudFrontのエンドポイントが違うリージョンにあるために、別のリージョンを跨いで新規に作成したS3バケットを探せるようになるまで最大24時間かかるようです。
つまり、一日後にまたアクセスしてみるか、以下のリンク先の記事のようにCloudFrontの
Origin Domain Name
Origin Domain Name(変更前):hoge.piyo.com.s3.amazonaws.com
👇(S3バケットのあるリージョンをつける)
Origin Domain Name(変更後):hoge.piyo.com.s3-ap-northeast-1.amazonaws.com
参照:
【CloudFront Functions版・作業①】S3でHtmlファイル等を準備
※ここからは2022年2月2日に更新した内容です。
基本的には
繰り返しになりますが、静的なウェブサイトホスティングでは、サブドメイン付きのURLと同じ名前をもつS3バケットを新規作成する必要があります。
先程の例で取得していたドメイン名
geek.tacoskingdom.com
CloudFront Functions
kabu-app.tacoskingdom.com
これも先程と同様にこのドメイン名と同じ名前のS3バケットを作成します。

繰り返しになりますが、ステータスコード404用の
index.html
<!doctype html>
<html lang="jp">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="Content-Style-Type" content="text/css; charset=UTF-8">
<meta http-equiv="Content-Script-Type" content="text/javascript; charset=UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body><h1>404 not found</h1></body>
</html>
このバケットにもパブリックなアクセスを与えるために、読み取り専用のポリシーを追加します。
まずこのバケットを選んで、
[アクセス許可]

次にバケットポリシーに
s3:GetObject
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Public Policy #2",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::kabu-app.tacoskingdom.com/*"
}
]
}

これでS3バケットの準備が完了しました。
【CloudFront Functions版・作業②】CloudFrontとCloudFront Functionsを設定する
次に
結局の話、CloudFront Functionsとは、CloudFrontディストリビューションにそっとお供えする廉価版Lambdaです。
よってCouldFront Functionsに出来ることは、LambdaやLambda@Edgeでも可能ですが、その逆だとCouldFront Functionsに出来ないことが沢山あります。
例えば、実装できるJavascriptのコードは、ES5以前の使用でしか受け付けないので実装には注意が必要です。
つまりCloudFront Functionsが動作している内部のランタイムは非常に古いし、マシーンのスペックはすこぶる低い...のでなんだかワケアリのハードウェアが割り当てられてるからこんなにお安いサービスになっていると考えておくと良いでしょう。
この点を鑑みて、CouldFront Functionsのテストの中で
コンピューティング使用率
CloudFront Functionsを作成・発行する
では早速、
[CloudFront] > [関数] > [関数を作成]ボタン

ここでは関数の名前を適当に
kabu-app-handler

CloudFront関数を新規作成すると、割とシンプルな設定項目が表示されます。
今回はs3バケットのルートフォルダのindex.htmlをリクエストするだけですので、
[関数コード]
function handler(event) {
const request = event.request;
const uri = request.uri;
if (!/index\.html$/m.test(uri)) {
if (/\/$/m.test(uri)) {
request.uri += 'index.html';
} else {
request.uri += '/index.html';
}
}
return request;
}
ではこの関数コードをテストをしましょう。

コードに問題が無ければこのCFファンクションを発行して、Liveステージにデプロイします。

CFファンクションをデプロイした直後は、どのCFディストリビューションにも紐付けされていません。

発行後に
[関連付けを追加]
(やっぱり)CloudFrontのディストリビューションを作成する
CFファンクションは、どれか最低一つのCFディストリビューションにそっと添える廉価版Lambdaなので、そもそも関連付け先のCFディストリビューション本体が無ければ機能しません。
まずは
同じブログ内でニ回も同じ手順を説明するのは面倒ですので、詳細の方は上記の内容に譲ります。
前項でも説明していましたが、サブドメインも含めたhttps付きのURLでアクセスしたい場合には、以前説明した
これでSSL証明が発行済になって
https://...

なおサブドメインのSSL証明は個別のサブドメイン名でも発行できますが、
ワイルドカード(*)
別の運営者でサブドメインを切り分けるような特別な理由も無い限りサブドメインが一括でSSL証明した方が効率的と言えます。
それはさておき、
ディストリビューションをポチポチと作成していくと、設定の中程で、以下の
[関数の関連付け - オプション]

ここで、
[ビューワーリクエスト]
CloudFront Functions
kabu-app-hander(先ほど作成したもの)
最近のAWSのダッシュボードはUIがかなりリニューアルしているので少し雰囲気が違いますが、先ほどと同様、各設定は以下のようにほぼデフォルトにしておきます。

CFディストリビューションを新規作成したら、S3のバケットポリシーもアップデートしておきます。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Public Policy #2",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity ***************"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::geek.tacoskingdom.com/*"
}
]
}
【CloudFront Functions版・作業③】Route53の設定する
仕上げに、Route53へこのサブドメインのAレコードを追加したら完了です。
これは
ルーティングの設定が有効になったら、
https://kabu-app.tacoskingdom.com

簡単な1枚だけのウェブページ程度ならばCFファンクションだけで事足りそうで、色々と応用の幅が広がりそうです。
まとめ
以上、サブドメイン名を使ったAWSによる静的ウェブサイトのホスティング方法を通常のCloudFrontを利用するケースと、新たにCloudFront Functionsを使うケースを追加して、2面を比較して詳しく解説してみました。
参考サイト
記事を書いた人
ナンデモ系エンジニア
主にAngularでフロントエンド開発することが多いです。 開発環境はLinuxメインで進めているので、シェルコマンドも多用しております。 コツコツとプログラミングするのが好きな人間です。
カテゴリー