サーバレスで静的Webサイトをホスティング＆自動デプロイする(CloudFront+ACM+Route53+S3+CodePipeline+Github)

# やりたいこと
* AWSのCloudFront+ACM+Route53+S3を利用し、サーバレスで静的Webサイトをホスティングする。
※WebサイトのソースはS3に配置する。
※AWS以外のサービスで取得した独自ドメインをRoute53に設定する。
※S3単体だとHTTPSは利用できないため、CloudFront&ACMを利用する。
※以下のURLでのアクセスを想定。HTTPはHTTPSにリダイレクトさせる。
```https://xxxx.com```
```https://www.xxxx.com```

* AWSのS3+CodePipelineとGithubを利用し、自動デプロイ環境を構築する。

# 構成イメージ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/95157a5a-b1e8-9a87-0719-568cefedb2c5.png)

# 手順(サマリー)
1. S3のバケットを作成する
2. CodePipelineを利用し、S3とGithubを連携する(自動デプロイ)
3. S3で静的Webサイトをホスティングする(外部公開する)
4. Route53に独自ドメインを登録する
5. ACMで証明書を作成する
6. CloudFrontのDistributionを作成する
7. CloudFront向けに独自ドメインを設定する
8. 動作確認(全体)

# 手順(詳細)
## 1. S3のバケットを作成する
静的WebサイトをホスティングするためのS3のバケットを作成する。

<img width="848" alt="スクリーンショット 2019-06-15 14.19.37.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/dad303c9-8f63-5df7-586d-1fb06d7f9bd8.png">

### 名前とリージョン
バケット名：```www.xxxx.com```　※バケット名=FQDNとして設定すること。
リージョン：お好みで。
![スクリーンショット 2019-06-01 3.06.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/728c58de-ef5e-017b-fcc8-9011c941c20e.png)

### オプションの設定
お好みで。基本的にデフォルトのままでOK。
![スクリーンショット 2019-06-01 3.07.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/407a386c-f4df-d225-986d-52fceb64280f.png)

### アクセス許可の設定
デフォルトのまま。後ほど設定する。
![スクリーンショット 2019-06-01 3.07.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/9d47d719-d531-df99-0234-c0288f2a04b8.png)

### 確認画面
<img width="1091" alt="スクリーンショット 2019-06-15 14.29.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/9e7a5cf9-6b8e-4ecd-a029-09164e422b61.png">

このようにS3のバケットが作成できた。
<img width="979" alt="スクリーンショット 2019-06-15 14.33.11.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/d33f15b1-b71c-94f5-4ccc-6b540c4edb4c.png">


## 2. CodePipelineを利用し、S３とGithubを連携する(自動デプロイ)
CodePipelineを利用し、GitHub上のソースをS3に自動的にデプロイする。

### パイプラインを作成する
![スクリーンショット 2019-06-01 2.57.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/4939ab9b-1f50-6c3a-facd-a1a85dd6f2e9.png)

### パイプラインの基本設定
基本的にデフォルトでOK。パイプライン名はわかりやすいものなら何でもOK。
![スクリーンショット 2019-06-01 2.58.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/269c3427-9c6c-c5d3-d902-938eff64bb0f.png)

### ソースステージを追加する
「GitHub」を選択する。
![スクリーンショット 2019-06-01 2.58.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/fd096a14-4aa6-e222-ea4c-4b818b776775.png)

GitHubを選択すると設定項目が現れるので、「GitHubに連携する」ボタンを押下する。
![スクリーンショット 2019-06-01 2.58.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/918e0a38-86a0-9e52-41d0-506fc259e9fc.png)

GitHubの認証ポップアップが表示されるので、指示に従い認証する。
![スクリーンショット 2019-06-01 2.59.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/895495e4-9e86-6ed0-5904-3cf5e3792d03.png)

認証に成功したら、連携対象のリポジトリとブランチを選択し、次へ。
※この例の場合、対象リポジトリのmasterブランチにPushすると、最新ソースがS3に自動的にデプロイされる。
![スクリーンショット 2019-06-01 2.59.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/0fd2ce06-9756-2b8e-4076-de310e651679.png)

### ビルドステージを追加する
特に何も設定せず、「ビルドステージをスキップ」を押下する。
![スクリーンショット 2019-06-01 3.01.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/591ca398-54dc-2301-224e-0c6f58f591c2.png)

確認ポップアップが表示されるが、気にせずスキップする。
![スクリーンショット 2019-06-01 3.01.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/bb27f883-2e39-196a-2443-28248574f061.png)

### デプロイステージを追加する
「Amazon S3」を選択し、次へ。
![スクリーンショット 2019-06-01 3.01.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/8d121297-7fe6-f20e-73c2-b2515346c9b1.png)

前工程で作成したS3のバケットを参照するよう各項目を入力する。
「デプロイする前にファイルを抽出する」にチェックを付ける。
<img width="1580" alt="スクリーンショット 2019-06-16 2.57.09.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/170d7ba7-4730-b1d8-73c2-b88e1d34b736.png">

### 確認画面
設定内容を確認し、問題なければパイプラインを作成する。
![スクリーンショット 2019-06-01 3.11.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/f4cdb6c1-b9e3-dd80-9e9d-997bcedd2b94.png)

### 動作確認
パイプラインの作成が完了すると自動的にデプロイが開始する。
以後、対象リポジトリの対象ブランチにPushされるたびにCodePipelineが自動的にソースをS3にデプロイしてくれる。
![スクリーンショット 2019-06-06 21.25.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/3d02e0d6-2316-1de0-63e7-f2634fa60924.png)

デプロイが完了したら、作成したS3にGitHub上のソースが反映されていることを確認する。
<img width="1305" alt="スクリーンショット 2019-06-15 14.58.20.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/c10eff0a-ed9c-6205-15c6-6cdd0d271364.png">

パイプライン作成後はGitHubのリポジトリにWebhookが登録されているか念のため確認しておく。
<img width="1005" alt="スクリーンショット 2019-06-16 2.25.14.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/883ce214-9496-9e2f-6fee-5eea8f8a1c23.png">

## 3. S3で静的Webサイトをホスティングする(外部公開する)
### ```Static website hosting```を有効にする
S3のバケットを開き、「プロパティ」タブの「Static website hosting」を選択する。
<img width="1235" alt="スクリーンショット 2019-06-15 22.39.36.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/ddc984ea-c91f-fb22-3093-d9e1df44facd.png">

「このパケットを使用してウェブサイトをホストする」を選択し、
インデックスドキュメントに「index.html」を入力し、保存する。
![スクリーンショット 2019-06-06 20.21.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/61908c09-4f10-a284-0b08-cd5e66c7f7b9.png)

紫チェックボックスと「パケットホスティング」が表示されていればOKです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/7327dd92-3a03-9c9f-db72-c9ff77180c8d.png)

### 公開設定

「アクセス権限」タブの「ブロックパブリックアクセス」を選択し、編集を選択する。
<img width="1212" alt="スクリーンショット 2019-06-15 22.58.35.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/43cc2135-0771-e6fb-bb02-4e16dcc04295.png">

赤枠のチェックを外して保存する。
<img width="1203" alt="スクリーンショット 2019-06-15 22.58.40.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/04ca80c6-42e8-ced3-849e-fd45a556404d.png">

「アクセス権限」タブの「パケットポリシー」を選択し、パケットポリシーエディタにポリシー設定のテキストを入力し、保存。
※以下テキストの```【S3バケット名を入力】```を作成済みのS3バケット名に置き換え、パケットポリシーエディタに貼り付ければOK。
<img width="1308" alt="スクリーンショット 2019-06-15 15.18.34.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/2d6d44c7-83a2-7d12-a1eb-0982f5113b00.png">

```
{
   "Version":"2012-10-17",
   "Statement":[{
    "Sid":"PublicReadForGetBucketObjects",
         "Effect":"Allow",
      "Principal": "*",
       "Action":["s3:GetObject"],
       "Resource":["arn:aws:s3:::【S3バケット名を入力】/*"
       ]
     }
   ]
 }
```

保存すると以下のようにパブリックの表示が出る。
※Webサイトとしてどこからでも誰からでも見られるようにするため、警告は無視してOK。
![スクリーンショット 2019-06-06 20.24.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/1f7e3471-a033-9522-ca90-9e071791cea3.png)

### 動作確認
先ほど操作した「Static website hosting」の以下の赤枠にサイトのURLが記載されているので、そのURLにアクセスし、問題なくWebサイトが表示されることを確認する。
※この時点ではまだHTTPでアクセスする。
<img width="1742" alt="スクリーンショット 2019-07-07 19.48.15.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/e41cc50d-7523-c22f-c716-754ead92544a.png">

## 4. Route53に独自ドメインを登録する
### ホストゾーンを作成
Route53のメニューから「ホストゾーン」をクリックする。
<img width="1278" alt="スクリーンショット 2019-06-15 16.38.26.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/dc8c5ddb-011f-898e-73fe-3f9dd9312865.png">

「ホストゾーンの作成」ボタンを押下すると右ペインに入力欄が表示されるので、利用するドメインを入力し、タイプは「パブリックホストゾーン」を選択し、「作成」ボタンを押下する。
<img width="1302" alt="スクリーンショット 2019-06-15 16.41.45.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/cc26ce6b-f6a3-b2c0-5500-79b484304138.png">

NSとSOAが自動的に作成される。
<img width="1295" alt="スクリーンショット 2019-06-15 16.44.59.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/5feff978-54aa-a2ed-2646-60412d491cfc.png">

## 5. ACMで証明書を作成する
HTTPSを利用する際に参照する証明書をACMで作成する。

### パブリック証明書のリクエスト
リージョン「バージニア北部」を選択した上で、「証明書のリクエスト」ボタンを押下する。
※CloudFrontでACMの証明書を利用する場合、証明書はリージョン「```バージニア北部（us-east-1)```」で取得する必要がある。
※ハマりポイント。

<img width="1260" alt="スクリーンショット 2019-06-15 16.16.52.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/4fd3adb2-c13c-f3ce-827f-4a90b9edd38f.png">

「パブリック証明書のリクエスト」を選択し、「証明書のリクエスト」ボタンを押下する。
<img width="1276" alt="スクリーンショット 2019-06-15 16.19.16.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/4ebcaaec-a03a-4b5a-7b15-15f79a06bea8.png">

以下の通り、ドメイン名を入力する。
1つ目：```*.xxxx.com```
※ワイルドカードで指定。

2つ目：```xxxx.com```
※「この証明書に別の名前を追加」ボタン押下で入力欄が表示される。

<img width="1341" alt="スクリーンショット 2019-06-13 19.52.51.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/caa94592-292e-e09c-052c-657c29001f1a.png">

「DNSの検証」を選択し、「確認」ボタンを押下する。
※これはお好みで。
<img width="1274" alt="スクリーンショット 2019-06-15 16.24.22.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/f94e4c0e-8bde-c21f-3bad-1328e88c4c8d.png">

確認画面で、入力内容が正しいか確認する。問題なければ、「確認とリクエスト」ボタンを押下する。
<img width="1242" alt="スクリーンショット 2019-06-15 16.24.30.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/7f05ef3b-436c-b1a5-4256-2ed1cd74d918.png">

### 証明書の検証

検証画面で検証用レコード(CNAME)が表示されるので、それをRoute53に登録する。
※独自ドメインをRoute53で管理する場合、「Route53でのレコードを作成」ボタンを押下することで、検証用レコード(CNAME)を自動的にRoute53に登録することができる。らくらく。
<img width="1341" alt="スクリーンショット 2019-06-13 19.53.39.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/530a73fb-030e-e753-6531-194809433849.png">

検証状況は証明書一覧から確認することができる。状況が「発行済み」に変わったら証明書の作成は完了。
<img width="1260" alt="スクリーンショット 2019-06-15 16.25.12.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/9a7d5656-a48b-3bbb-3892-54d00d37736d.png">

## 6. CloudFrontのDistributionを作成する
### Distributionを作成する
CloudFrontの設定画面を開き、「Create Distribution」ボタンを押下する。
![スクリーンショット 2019-06-07 11.14.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/91d9a4ac-8d6f-9076-aaac-f4722f651ce6.png)

Web側の「Get Started」ボタンを押下する。
![スクリーンショット 2019-06-07 11.14.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/064206f3-47c5-9404-da4a-01643e6deddf.png)

「Origin Domain Name」の入力欄をクリックし、前工程で作成したS3バケット名を選択する。
![スクリーンショット 2019-06-07 11.16.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/b9a2f988-4898-7875-d775-e6c234b043be.png)

「OriginID」が自動的に割り当てられる。それ以外は基本的にデフォルトでOK。
![スクリーンショット 2019-06-07 11.16.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/af4b58cd-f920-756d-cef2-c8d61f43d527.png)

「Viewer Protocol Policy」では「Redirect HTTP to HTTPS」を選択する。
TTLはお好みで設定。
それ以外は基本的にデフォルトでOK。
![スクリーンショット 2019-06-07 11.16.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/e15c486f-f3df-7dfd-db46-61b8ef082cc4.png)

「Alternate Domain Names(CNAMEｓ)」に以下の通りドメインを入力する。
```xxxx.com,www.xxxx.com``` ※カンマ区切り
「SSL Certificate」は「Custom SSL Certificate」を選択し、前工程で作成したACMの証明書を選択する。
「Default Root Object」には「index.html」を入力する。
それ以外は基本的にデフォルトでOK。
<img width="1085" alt="スクリーンショット 2019-06-16 0.01.38.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/8282e3be-e5ac-b6d5-d894-2c5d4112cd8f.png">
<img width="731" alt="スクリーンショット 2019-06-16 0.01.46.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/7fff0bb8-2d72-afdd-95e7-8453106d86c8.png">

### 動作確認
Distributionが作成されるまで少々時間がかかる。
「Status」が「Deployed」、「State」が「Enabled」になるまで待つ。
↑の状態になったら、「Domain Name」の「xxxx.cloudfront.net」のドメインにアクセスし、Webサイトが正常に表示されることを確認する。
<img width="1794" alt="スクリーンショット 2019-07-07 21.13.17.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/c1839d42-116f-8c4c-850e-1c1ce1edf0fc.png">

## 7. CloudFront向けに独自ドメインを設定する
### レコードセットを作成
前工程で操作したRoute53の設定画面を開き、「レコードセットの作成」を押下し、以下の通りAレコードのエイリアスを設定する。
名前：```独自ドメイン(xxxx.com)```
タイプ：```A - IPv4 Address```
エイリアス:```はい```
エイリアス先:```前工程で作成したCloudFrontのDistribution(xxxx.cloudfront.net)```
※それ以外は基本的にデフォルトでOK。
※「www.xxxx.com」などサブドメインやMXレコードなどもこのタイミングで作成してOK。
<img width="1597" alt="スクリーンショット 2019-06-16 2.31.17.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/282b723f-c566-08b1-a47b-efe65d7e85e8.png">

## 8. 動作確認(全体)
* 以下のURLにアクセスし、SSLが正常に動作すること、Webサイトが正常に表示されることを確認する。  
```https://xxxx.com```  
```https://www.xxxx.com```
* HTTPでアクセスした場合、HTTPSにリダイレクトされることを確認する。  
```http://xxxx.com```  
```http://www.xxxx.com```
* GitHubの対象リポジトリ、対象ブランチにPushしたら自動デプロイが動作し、変更内容がCloudFront側に正しく反映されることを確認する。

以上、全行程おわり。

# その他
* 実運用する場合、要求仕様にあわせて設定などを諸々最適化すること。
* CloudFrontのキャッシュにより、自動デプロイを実行しても最新の変更内容を即座に確認できないため注意。
早めに確認したい場合は以下の記事を参考にキャッシュを削除するとよい。  
[[AWS] Amazon CloudFrontのキャッシュ削除(Invalidation)](https://dev.classmethod.jp/server-side/aws-amazon-cloudfront-deleting-cache-by-invalidation/)

# 参考
* [CodePipelineでGitHub上のコードをS3にデプロイする](https://www.kabegiwablog.com/entry/2019/02/19/100000)
* [独自ドメインを使ってAmazon S3で静的Webサイトをホストする](https://qiita.com/Ichiro_Tsuji/items/c174d580587a622d3358)
* [CloudFront で S3 静的ウェブサイトホスティングを SSL/TLS に対応させる](https://dev.classmethod.jp/cloud/aws/tls-for-s3-web-hosting-with-cloudfront/)