【AWS】静的なウェブサイトホスティングのハンズオン

# 1.はじめに
はじめまして！私は、ＡＲＩで23年から働き始めた新卒1年目のエンジニアです。
Qiitaを書くのが初めてなので至らない点があると思いますが、ご了承ください...
**こちらはARIのアドベンドカレンダー21日目の記事となります！**

https://qiita.com/advent-calendar/2023/ari-group

AWSを勉強し始めてから半年ほど経ったのですが、最初から構築したことのあるサービスが全然ないことに気づいたのでハンズオンをしてみた記録を書き起こしていこうと思います。

# 2.ハンズオンの説明
### 2-1.ハンズオンの概要
本記事では以下にあるAWS公式のハンズオンを参考に実施してみた記録になります。

https://pages.awscloud.com/JAPAN-event-OE-Hands-on-for-Beginners-StaticWebsiteHosting-2022-reg-event.html?trk=aws_introduction_page

今回のハンズオンでは、上記サイトのタイトルにもある通りHTMLなどで作成した静的なコンテンツを世界に公開するといった内容となります。
※上記ハンズオンではオプションとしてRoute53でドメインを取得する手順も説明してありますが、本記事ではドメイン名の取得は行いません。

### 2-2.構成
今回は以下の画像にあるように、S3バケットに入っているHTMLファイルをCloudFront経由で見ることができる構成を作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622326/54709ccd-f52a-247e-cfda-c30629cb2531.png)

※本記事では各サービスの細かい説明は割愛させていただきます。。

# 3.ハンズオンの実施
### 3-1.S3バケットの作成
まずS3バケットを作成していきます。
コンソールにログイン後、S3の画面へ移動して「バケットを作成」をクリックすると以下バケット作成画面へ遷移します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622326/eeca0101-50ad-719b-e0e5-9176b0a45c20.png)
※以下では注意点やデフォルトの設定以外で操作する項目をピックアップして説明しています。

**AWSリージョン**
今回は東京リージョンで作成していくので、リージョンは「アジアパシフィック (東京) ap-northeast-1」を選択します。

**バケット名**
次にバケット名の入力を行います。
ここで注意点が3つあります。

**1\. バケット名は世界で一意（ユニーク）である必要がある。**
S3のバケット名は、アカウントが別であったとしても世界で同じ名前のものが作成できないようになっているので注意が必要です。
※もし名前がかぶってしまった場合、作成時にエラーのメッセージが出てきます。

**2\. バケット命名規則に従う必要がある。**
バケット名は命名規則があり、文字数や使える文字の種類に制限があります。
例えば、文字数であれば3～63文字の長さで作成しないといけない、
使える文字は小文字、数字、ドット (.)、ハイフン(－)のみなどです。
[公式ドキュメント](https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucketnamingrules.html?icmpid=docs_amazons3_console)に詳細なバケットの命名規則が書いてあります。

**3\. ドメインとバケット名をそろえる必要がある。**
この注意点は後述するRoute53で独自ドメインを取得する場合になります。
取得するドメイン名とバケット名が同じにする必要があります。
既に取得しているドメイン名を使用する場合は、そのドメイン名をバケット名につけます。

**このバケットのブロックパブリックアクセス設定**
次にバケットのパブリックアクセスをブロックするかどうかの設定を行います。

今回のS3バケットの用途は、Webサイトホスティングとして世界に公開するので「パブリックアクセスをすべてブロック」のチェックを外します。
チェックを外すと、オブジェクト（バケットの中身）が公開されるという旨のメッセージが表示されるため、承認するチェックを入れます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622326/adccb90c-c699-3b18-68c9-63e5c3d20552.png)

以上の選択/入力項目の操作が完了したら、ページ下部にある「バケットを作成」ボタンをクリックします。

以上の手順で静的ウェブサイトをホスティングするバケットができました！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622326/202b130a-9989-f47f-27b1-065101205458.png)

**バケットの追加設定**
作成したバケットのバケット名の部分をクリックします。
↓バケットが複数ある場合は検索バーでバケット名を検索すると絞り込めます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622326/5560ebb7-1c8a-f83c-133c-ba159e727636.png)

作成したバケットを開き、プロパティのタブをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622326/0728196d-50fb-dbe1-66b0-e37ccf30155d.png)

プロパティタブに移動後、「静的ウェブサイトホスティング」の項目で編集ボタンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622326/fc126dc0-7e14-fd58-2c47-d8476d860f4e.png)

編集画面移動後に次の操作を行います。
1\. 編集画面で、静的ウェブサイトホスティングの「有効にする」を選択。
2\. インデックスドキュメントに「index.html」を入力。
※インデックスドキュメントで設定したページがウェブサイトのホーム（デフォルト）ページとなります。
3\. 「変更の保存」ボタンをクリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622326/6b1a84ff-2de3-567a-e4ea-02a74930d8d7.png)


上記の設定変更が完了後、以下の画像のようにバケットのプロパティで静的ウェブサイトホスティングが有効になっていることを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622326/6fd8a1ff-2328-0aec-69fd-930392b06b35.png)

**アクセス許可の設定**
次に、作成したS3にバケットポリシーを追加して、URL（バケットウェブサイトエンドポイント）を知っている人がアクセスできるようにします。
ここで入力するポリシーは静的ウェブサイトホスティングができているか確認するためのものになるので、後ほどポリシーを変更します。

1\. アクセス許可タブをクリックする。
2\. バケットポリシーの編集ボタンをクリックする。
3\. 編集画面で以下コードを入力し、変更の保存ボタンをクリックする。
```json
{
  "Version": "2012-10-17",
  "Statement": [
      {
          "Sid": "PublicReadGetObject",
          "Effect": "Allow",
          "Principal": "*",
          "Action": [
              "s3:GetObject"
          ],
          "Resource": [
              "arn:aws:s3:::s3bucketname/*"
          ]
      }
  ]
}
```
※ここで「arn:aws:s3:::s3bucketname/*」の「s3bucketname」には上記S3作成時に設定したバケット名を入力します。

### 3‐2.オブジェクトの追加
ここでは後ほど作成するCloudFrontからユーザーがアクセスした際に画面に表示されるウェブサイトの画面（オブジェクト）をS3バケットに追加します。

**index.htmlファイルの作成**
S3バケットに追加するオブジェクト（今回はindex.html）を以下手順で簡単に作成します。

1\. メモ帳などのテキストファイルを開きます。
2\. テキストファイルに画面に表示される文字を入力します。
（今回は簡単にAWS S3 CloudFront hands-onという内容を画面に表示させてみます。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622326/3fa589b0-8179-69b7-bb19-51797673489c.png)
3\. 「index.html」と名前を付けて保存します。

**S3バケットにオブジェクトを追加する**
先ほど作成したindex.htmlファイルをS3バケットに追加していきます。

3-1で作成したS3バケットのオブジェクトタブをクリックしてオブジェクトの画面を開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622326/951bc9b8-621c-2240-2576-466a8fc4bd6b.png)


上記画面に移動後、先ほど作成したindex.htmlを以下の手順でアップロードします。
1\. エクスプローラーを開き、index.htmlを保存した場所に移動する。
2\. index.htmlをドラッグ&ドロップする。
3\. アップロードボタンをクリックする。

これでS3バケットにオブジェクトが追加できました。
以下の画像のようにS3バケットのオブジェクトでindex.htmlが確認できればOKです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622326/38047c66-adb4-48fe-a5d8-0ef5e47a3c75.png)

### 3‐3.index.htmlにアクセスできるか確認
3-1,3-2を行った結果、ブラウザでURL（バケットウェブサイトエンドポイント）を検索するとindex.htmlが見れるようになったはずなので確認してみます。
S3のプロパティタブから、静的ウェブサイトホスティングの部分に移動し、バケットホスティングをコピーします。以下画像の赤い□で囲まれた部分をクリックするとコピーできます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622326/bc2de273-8cfb-c2af-78fd-ddd3bd5727c5.png)

次にブラウザの検索バーにコピーしたURLをペーストしてEnterを押すと以下のような画面が表示されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622326/a8d75a91-1e11-1340-c623-d1f37c83e51e.png)

このURLを知っていれば、異なるブラウザやスマホなど別の端末からでもアクセスできます。


### 3-4.CloudFrontの作成
S3に追加したオブジェクトを見ることができたので、次はCloudFrontを経由してアクセスしてみようと思います。

**ディストリビューションを作成**
以下手順でCloudFrontの作成を行います。

コンソールの検索バーに「CloudFront」と入力してCloudFrontの画面に移動する。
「ディストリビューションを作成」ボタンをクリックする。

**オリジンドメイン**
オリジンドメインのバーをクリックすると既存のS3などがプルダウン形式で表示されるので、作成したS3バケット名が含まれているドメイン名を選択します。
→オリジンドメインを選択すると自動的に名前も入力されます。

**オリジンアクセス**
オリジンアクセスは「Origin access control setting(recommended)」を選択します。
Origin access controlの「コントロール作成」ボタンをクリックします。
コントロール作成画面では名前にオリジンで選択したS3の名前が自動で入るので、そのまま特に操作せずに作成ボタンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622326/e21e397f-f48e-09e0-08f5-2e28e7bb75df.png)

↓Origin access controlの「コントロール作成」画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622326/99d04b6f-a67e-57e3-75b4-b69daa0d4b6e.png)

**ウェブアプリケーションファイアウォール（WAF）**
「セキュリティ保護を有効にする」を選択します。
※どちらか選択しないとディストリビューションを作成できないので選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622326/e5bce782-aacf-81ae-b11e-1c1c4c3899dd.png)

以下は任意になりますが使いやすくするという意味で書きます。


**デフォルトルートオブジェクト-オプション**
「index.html」を入力します。

**説明**
ディストリビューションの一覧画面ではIDやドメイン名がぱっと見でわかりにくいので、わかりやすいように説明を入力します。

以上の操作が完了したら「ディストリビューションを作成」ボタンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622326/c03894a7-25d6-e0fc-7595-7b9e7b6dd126.png)

作成がうまくいくと次の画像のように表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622326/258854a0-1bdd-dc12-9251-48009d482493.png)

作成後、ディストリビューションが使えるようになるまで数分かかるので待機します。
↓の最終変更日が「デプロイ」から作成日時に変わるとブラウザからアクセスできるようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622326/317e699d-5e54-7574-c68d-e42cf8a7ee05.png)

**バケットポリシーの変更**
ディストリビューション作成後に以下画像の表示がされるので、S3バケットポリシーの変更を行います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622326/87ee22df-3174-a8ef-7ee9-f8d517fe28a7.png)
上記画像にある「ポリシーをコピー」ボタンをクリックし、「S3バケットの権限に移動してポリシーを更新する」をクリックします。

移動後、バケットポリシー編集画面で、ポリシー入力欄にコピーした内容をペーストします。
※すでに入力してあるS3作成時のポリシーはここで消します。
ペーストしたら変更を保存します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622326/66bb176d-b463-0ca3-eddb-6cbdff6e8319.png)

### 3-5.CloudFrontからアクセスできるか確認
バケットポリシーなどの設定が完了し、ディストリビューションが使えるようになったのを確認出来たら、CloudFront経由でアクセスできるか確認します。

1\. コンソールでCloudFrontの画面に移動する。
2\. 作成したディストリビューションのIDをクリックする。
3\. 一般タブの詳細にあるディストリビューションドメイン名をコピーする。
4\. ブラウザの検索バーにコピーしたドメイン名をペーストしてEnterを押す。
5\. 3-3でも確認できたindex.htmlの画面が表示されたか確認する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622326/ea019f8a-8503-8516-f043-e4e5a9d11dbe.png)

以上で今回目的であるS3の静的ウェブサイトホスティングが完了しました！

# 4.作成したリソースの削除
サービスの無料枠に収まっている場合もありますが、場合によっては課金が発生する可能性があるので作成したリソースの削除を行っていきます。

### 4-1.オブジェクトの削除
S3バケットを削除するために、バケットを空にする必要があるので、以下の手順でS3バケットに入っているオブジェクト（index.html）の削除を行い、バケットを空にします。
※他にもS3バケット削除前に空にする方法があるのですが1パターンだけ説明します。

1\. 作成したS3バケットを開く。
2\. オブジェクトの画面で、index.htmlの横のチェックボックスにチェックを入れる。
（オブジェクトの名前横にあるチェックボックスにチェックを入れると複数オブジェクトある場合に全選択になるため今回はどちらでもOKです。）
3\. 削除ボタンを押す。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622326/580d290a-923e-95cc-3810-2287d9748ab4.png)
4\. オブジェクトを完全に削除しますか？の項目に「完全に削除」を入力する。
5\. 「オブジェクトの削除」ボタンをクリックする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622326/3503cdeb-2d39-9f9d-18de-75d2c43cd83f.png)
以上でS3バケットが空になりました。

### 4-2. S3バケットの削除
次に空になったS3バケットの削除を行います。

1\. コンソールのS3バケットの一覧の画面に戻り、今回作成したバケットを選択する。
2\. 「削除」ボタンを押す。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622326/cb7cbfc5-b03b-9554-52ab-2b9c5ca2b849.png)
3\. 画面移動後、「バケット「バケット名」を削除しますか?」の項目に削除するバケット名を入力する。
4\. 「バケットを削除」ボタンをクリックする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622326/c46528e2-d289-ddcd-2e45-a3d54c276eff.png)
以上で作成したS3バケットの削除が完了しました。

### 4-3. CloudFrontの削除
最後に以下の手順でCloudFrontの削除を行います。

1\. コンソールのCloudFront画面に移動する。
2\. 削除するCloudFrontディストリビューションのIDを選択して「無効」ボタンをクリックする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622326/d22129ae-2fdd-f9a1-62d2-2763ec7e4b5f.png)
3\. ディストリビューションのステータスが無効になるまで待機する。
※コンソール上で無効に変更しても、デプロイ中の可能性があるのでディストリビューションを開いて、最終変更日が日時に変更するまで待機する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622326/e669e82b-735e-4897-1bf9-2557be864da4.png)
4\. ステータス変更後、再度ディストリビューションIDを選択し、「削除」ボタンをクリックする。
5\. 削除するかどうかを確認するポップアップが出るので、削除するディストリビューションが合っているか確認して「削除」ボタンをクリックする。

以上で今回作成したリソースのS3バケット、CloudFrontディストリビューションが削除できました。
ハンズオンの内容としては以上となります！

# 5.おわりに
今回はAWS公式のハンズオンを参考にしながら静的ウェブサイトホスティングに挑戦してみました。
今までAWSについて勉強をしていたので、今回使用したサービスがどのようなサービスなのかはふんわり把握していましたが、ハンズオンで実際に設定値などを触ってみることで、より具体的にイメージできるようになりました。

以下に自分が今回のハンズオンを行うにあたって間違えてしまった部分などをまとめます。

* **AWS公式のハンズオン資料が古いため、コンソール画面が実際の画面と異なっていた。**
今回実施したハンズオンの資料が数年前のだったので、コンソールの画面が2023年12月時点のものと異なっていました。
また、設定内容もハンズオンでは説明していなかったが、今回実施時点では設定しないとディストリビューションが作成できない、といった部分もありました。
なので詰まってしまった際は、都度他サイトや上司のアドバイスを参考に進めました。
* **バケットポリシーについて**
今回の記事ではバケットポリシーを正しく設定できず、CloudFront経由でindex.htmlにアクセスする際に詰まってしまいました。
原因としては、ハンズオンのバケットポリシーとCloudFrontのオリジンアクセスで提供されるバケットポリシーを組み合わせて設定したので、うまくアクセス許可ができていなかったことです。
本記事でもあるように組み合わせるのではなく、CloudFront作成時にコピーできるバケットポリシーだけを設定することでうまくアクセス許可ができるようになりました。

今回のハンズオンでは、以上の部分を間違えてしまいましたが、特に学びになった点になります。
（当たり前ですが、バケットポリシーはちゃんと意味を理解して書くべきですね、、笑）

今後は他のサービスのハンズオンの実施や、今回構築した構成プラスアルファでいじってみたいです！
まだまだ勉強が必要だと痛感しました、、。

以上、最後まで読んでいただきありがとうございました！

**【参考】**
* [AWS Hands-on for Beginners AWS 上で静的な Web サイトを公開しよう！](https://pages.awscloud.com/JAPAN-event-OE-Hands-on-for-Beginners-StaticWebsiteHosting-2022-reg-event.html?trk=aws_introduction_page)
* [【やってみた】Amazon CloudFrontとAmazon S3を使って、静的サイトを作ってみた](https://techblog.nhn-techorus.com/archives/21488)
* [CloudFrontとS3で作成する静的サイト構成の私的まとめ](https://dev.classmethod.jp/articles/s3-cloudfront-static-site-design-patterns-2022/)