サブドメイン付きURLで静的なWebサイトをAWS S3/CloudFront(とCloudFront Functions)/Route53で作成する


※ 当ページには【広告/PR】を含む場合があります。
2021/03/10
2022/02/03
[Lambda@Edge x ウェブサイト運用] AWS S3上で静的ホスティングしたウェブサイトのアクセスURLに'/index.html'を補完する




ウェブサイトのお引越しは管理者にとっても大変な作業です。

AWS S3/Clounflont/Route53を利用した静的ウェブサイト のホスティングは結構昔から知られていて、未だに多くの記事もウェブ検索すると色々な解説記事を目にします。
個々数年利用可能になったCloudFrontの軽量サービス版である
「AWS CloudFront Functions」 が使えるようになったことで、この静的サイトホスティングが更に簡単に、安価にできるようになりました。
さて、サブドメイン付きのURLでのパターンはネット検索しても技術記事の少なさそうな感じがしましたので、ここでまとめておきます。


合同会社タコスキングダム|蛸壺の技術ブログ【AWS独習術】AWSをじっくり独学したい人のためのオススメ書籍&教材特集
図解即戦力 Amazon Web Servicesのしくみと技術がこれ1冊でしっかりわかる教科書

サブドメイン付きのウェブサイト?



複合的な業態をもつ企業などが自社のウェブサイトの運用に採用している場合がほとんどです。
例えば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を使うケース と、 後半にCloudFront Functionsを使うケース に別けて仕込みの手順を説明しています。


合同会社タコスキングダム|蛸壺の技術ブログ【AWS独習術】AWSをじっくり独学したい人のためのオススメ書籍&教材特集
図解即戦力 Amazon Web Servicesのしくみと技術がこれ1冊でしっかりわかる教科書

【通常CloudFront版・作業①】S3でHtmlファイル等を準備



ここからは実際の作業です。
まずは
AWS S3のダッシュボード から静的ウェブサイト用のS3バケットを作成していきます。

バケットの作成



まずは静的なウェブサイトホスティングでは、サブドメイン付きのURLと同じ名前をもつS3バケットを新規作成する必要があります。
今回は弊社の保有しているドメイン名に、サブドメインを付けてた以下のURLにウェブサイトを作成してみます。

            geek.tacoskingdom.com

        
合同会社タコスキングダム|蛸壺の技術ブログ



S3のリージョンはお好みで選択できますが、弊社は西日本ですのでなんとく最近出来た大阪リージョンを選んでみました。
バケット名の他はデフォルト値で
[バケットを作成] ボタンを押して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 の部分を読み替えたもので以下のjsonの内容を修正してお使いください。

            {
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Public Policy #1",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::geek.tacoskingdom.com/*"
        }
    ]
}

        

これでひとまずはS3での作業はOKです。


合同会社タコスキングダム|蛸壺の技術ブログ【AWS独習術】AWSをじっくり独学したい人のためのオススメ書籍&教材特集
図解即戦力 Amazon Web Servicesのしくみと技術がこれ1冊でしっかりわかる教科書

【通常CloudFront版・作業②】CloudFrontを設定する



次はCloudFrontダッシュボードから作業します。
なお、サブドメインも含めたhttps付きのURLでアクセスしたい場合には、以前説明した
AWS Certificate ManagerでSSL証明書の発行 の記事で解説しています。
ここでは既に
AWS Certificate Manager からSSL証明が発行済になってhttpsを使えるようにしている状態から話を始めさせていただきます。
まずは新しいCFディストリビューションを作成します。

合同会社タコスキングダム|蛸壺の技術ブログ


上の図では
Create Distribution の変更点を下線でマークしましたが、他の設定項目はひとまずデフォルト値で構いません。 (心配せずとも間違った値は後で編集可能です)
ご自身のドメインで試される場合には
geek.tacoskingdom.com のところを置き換えたような設定で試してみてください。
地味な設定で、
Default Root Objectindex.html を指定しないとCloudFrontがどこを見に行くと良いのか分からずに機能しませんので良く確認しましょう。
設定できたら下部の
[Create Distribution] ボタンで作成します。
CloudFrontのダッシュボードトップに戻ると、先程新規作成したディストリビューションが
in Progress になっていたら作成中ですので、デプロイされるまで〜15分程待ちます。

合同会社タコスキングダム|蛸壺の技術ブログ

S3バケットポリシーの修正



上のCFの設定で、
Grant Read Permissions on BucketYes, 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の`CloudFront Origin Access Identity <ID値>`に絞っておきたいので、'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バケット側をホスティングしてくれているようです。


合同会社タコスキングダム|蛸壺の技術ブログ【AWS独習術】AWSをじっくり独学したい人のためのオススメ書籍&教材特集
図解即戦力 Amazon Web Servicesのしくみと技術がこれ1冊でしっかりわかる教科書

【通常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

        


参照:
S3+CloudFrontでS3のURLにリダイレクトされてしまう場合の対処法
合同会社タコスキングダム|蛸壺の技術ブログ【AWS独習術】AWSをじっくり独学したい人のためのオススメ書籍&教材特集
図解即戦力 Amazon Web Servicesのしくみと技術がこれ1冊でしっかりわかる教科書

【CloudFront Functions版・作業①】S3でHtmlファイル等を準備



※ここからは2022年2月2日に更新した内容です。
基本的には
上記の節で説明した手順 と同じです。
繰り返しになりますが、静的なウェブサイトホスティングでは、サブドメイン付きのURLと同じ名前をもつS3バケットを新規作成する必要があります。
先程の例で取得していたドメイン名
geek.tacoskingdom.com は現在弊社のブログとしておかげさまでご愛好賜りながら運用させて頂いているので、以下の新たに取得したサブドメインで、今回の CloudFront Functions を使った方法を説明していきます。

            kabu-app.tacoskingdom.com

        

これも先程と同様にこのドメイン名と同じ名前のS3バケットを作成します。

合同会社タコスキングダム|蛸壺の技術ブログ


繰り返しになりますが、ステータスコード404用の
index.html をこのS3バケットにもアップロードしておきます。

            <!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バケットの準備が完了しました。


合同会社タコスキングダム|蛸壺の技術ブログ【AWS独習術】AWSをじっくり独学したい人のためのオススメ書籍&教材特集
図解即戦力 Amazon Web Servicesのしくみと技術がこれ1冊でしっかりわかる教科書

【CloudFront Functions版・作業②】CloudFrontとCloudFront Functionsを設定する



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

CloudFront Functionsを作成・発行する



では早速、
[CloudFront] > [関数] > [関数を作成]ボタン をクリックします。

合同会社タコスキングダム|蛸壺の技術ブログ


ここでは関数の名前を適当に
kabu-app-handler と付けておきます。

合同会社タコスキングダム|蛸壺の技術ブログ


CloudFront関数を新規作成すると、割とシンプルな設定項目が表示されます。
今回はs3バケットのルートフォルダのindex.htmlをリクエストするだけですので、
[関数コード] を以下のJsスクリプトで置き換えます。

            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ディストリビューションにも紐付けされていません。

合同会社タコスキングダム|蛸壺の技術ブログ


発行後に
[関連付けを追加] ボタンから既存のCFディストリビューションを割り当てることもできますが、今回はこのCFファンクションに紐付けできるCFディストリビューションを新規作成していきます。

(やっぱり)CloudFrontのディストリビューションを作成する



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

合同会社タコスキングダム|蛸壺の技術ブログ


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

合同会社タコスキングダム|蛸壺の技術ブログ


ここで、
[ビューワーリクエスト] から関数タイプ・ CloudFront Functions 、関数ARN/名前・ 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/*"
        }
    ]
}

        

合同会社タコスキングダム|蛸壺の技術ブログ【AWS独習術】AWSをじっくり独学したい人のためのオススメ書籍&教材特集
図解即戦力 Amazon Web Servicesのしくみと技術がこれ1冊でしっかりわかる教科書

【CloudFront Functions版・作業③】Route53の設定する



仕上げに、Route53へこのサブドメインのAレコードを追加したら完了です。
これは
先程の項目 と全く同じ手順ですので説明を省略します。
ルーティングの設定が有効になったら、
https://kabu-app.tacoskingdom.com へアクセスしてみますと、下の図のようにCloudFront Functions版ウェブサイトがほぼ待ち時間無しで立ち上がっていると思います。

合同会社タコスキングダム|蛸壺の技術ブログ


簡単な1枚だけのウェブページ程度ならばCFファンクションだけで事足りそうで、色々と応用の幅が広がりそうです。


合同会社タコスキングダム|蛸壺の技術ブログ【AWS独習術】AWSをじっくり独学したい人のためのオススメ書籍&教材特集
図解即戦力 Amazon Web Servicesのしくみと技術がこれ1冊でしっかりわかる教科書

まとめ



以上、サブドメイン名を使ったAWSによる静的ウェブサイトのホスティング方法を通常のCloudFrontを利用するケースと、新たにCloudFront Functionsを使うケースを追加して、2面を比較して詳しく解説してみました。

参考サイト

Route 53 にサブドメインを設定する2種類の方法
記事を書いた人

記事の担当:taconocat

ナンデモ系エンジニア

主にAngularでフロントエンド開発することが多いです。 開発環境はLinuxメインで進めているので、シェルコマンドも多用しております。 コツコツとプログラミングするのが好きな人間です。

合同会社タコスキングダム|蛸壺の技術ブログ【AWS独習術】AWSをじっくり独学したい人のためのオススメ書籍&教材特集