AWS CLIで Web サイトを構築、管理、運用する(1日目)

ひとりアドベントカレンダーということで、AWS CLI でいろいろやっちゃうシリーズをお送りします。
当面は、AWS CLIでWebサイトを構築、管理、運用するといった具合です。

# 1日目の要約
Web サイトをさくっとたてるよ！

# AWS CLI の準備
このあたりをみて、好きなバージョンとお使いのOSにあった環境設定をしてくださいね。
なんなら、 AWS CloudShell で実行するのも楽でよいと思います。
この記事シリーズは、AWS CloudShell で実行し、実行例を載せています。

バージョン１
https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/install-cliv1.html

バージョン２
https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/install-cliv2.html

# 構成図
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/344161/77071904-7d50-dcf5-95e7-54b514d0e1a9.png)

# 概要
Amazon Simple Storage Service(Amazon S3)の静的 Web ホスティング機能を AWS CLI で設定、構築する

# さあ、やってみよう！
## S3 関係のコマンドの確認
S3 に関する AWS CLI のコマンドは以下の通りです。

* s3
 * ファイルの転送などに使う 
 * 高レベル(S3)コマンドともいう
* s3api
 * S3 の API を操作するのに使う
* s3control
 * アカウントレベルでの S3 操作・設定を行うコマンド
 * この記事では使いません
 
## S3 Bucket を作る
S3 Bucket を作成する際、まずはじめに気を付けないとならないのがバケット名の命名規則に準じているかです。

* バケット名は 3 ～ 63 文字の長さで、小文字、数字、ピリオド、ダッシュのみを使用できます。
* バケット名の各ラベルは、小文字または数字で始まっている必要があります。
* バケット名では、アンダースコア、末尾のダッシュ、連続するピリオド、隣接するピリオドとダッシュは使用できません。
* バケット名を IP アドレス (198.51.100.24) として書式設定することはできません。

あと、一番大事なのが、ほかの利用者やアカウント含めて被らないようにしないとならないということです。
以下の例では、生成した uuid を用いることで回避できるようにしています。

使用するコマンドは、 s3api create-bucket コマンドです。

```sh
BUCKETNAME=`uuidgen`
aws s3api create-bucket --bucket ${BUCKETNAME} \
--region ap-northeast-1 \
--create-bucket-configuration LocationConstraint=ap-northeast-1

```

実行すると以下の様に出力されます。

```json
{
    "Location": "http://<BUCKETNAME>.s3.amazonaws.com/"
}
```

## コンテンツを作る
適宜 HTML ファイルを作ってください。見本は以下の通り。

```HTML:index.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <title>Advent calendar 2021</title>
</head>
<body>
  <h1>Hello world!!</h1>
</body>
</html>
```

## S3 へコンテンツをアップロードする
作ったコンテンツ(ファイル)を S3 にアップロードします。
ファイルは、カレントディレクトリにある前提で実行例を載せています。

使用するコマンドは s3 cp コマンドです。

```sh
# 同じシェルをそのまま使える場合は環境変数を使う
aws s3 cp index.html s3://${BUCKETNAME}/index.html

# 閉じてしまったなどで使えない場合は、バケット名を自分で指定してください。
#aws s3 cp index.html s3://<BUCKETNAME>/index.html
```

無事にアップロードできると、以下の様に出力されます。

```sh
upload: ./index.html to s3://<BUCKETNAME>/index.html
```

## S3 バケットにファイルが格納できたか確認する
アップロード時のコマンド出力でアップロードができたことが確認できていますが、念のために、s3 ls コマンドをつかって存在するかも確認します。

```sh
# 同じシェルをそのまま使える場合は環境変数を使う
aws s3 ls s3://${BUCKETNAME}/

# 閉じてしまったなどで使えない場合は、バケット名を自分で指定してください
#aws s3 ls s3://<BUCKETNAME>/
```

ファイルが格納されていれば、以下の様に出力されます。

```sh
YYYY-MM-DD hh:mm:ss    134 index.html
```

S3 バケットに格納されていることが確認できました。

## 静的 Web ホスティングの設定を有効化する
ファイルが格納できたので、次は、お待ちかねの、Web サーバの構築もとい、静的 Web ホスティングの有効化です。

今回は簡単に有効化するため s3 website コマンドで実行します。
細かな設定をしたい場合は、s3api put-bucket-website コマンドを使います。

```sh
# 同じシェルをそのまま使える場合は環境変数を使う
# コンテンツのファイル名が異なる場合は適宜変更する
aws s3 website s3://${BUCKETNAME}/ --index-document index.html

# 閉じてしまったなどで使えない場合は、バケット名を自分で指定してください。
#aws s3 website s3://<BUCKETNAME>/ --index-document index.html
```

正常に終了した場合は、特に応答なしです。

s3api get-bucket-website コマンドを実行することで有効化されているかが確認できます。

```sh
# 同じシェルをそのまま使える場合は環境変数を使う
aws s3api get-bucket-website --bucket ${BUCKETNAME}

# 閉じてしまったなどで使えない場合は、バケット名を自分で指定してください。
#aws s3api get-bucket-website --bucket <BUCKETNAME>
```

有効化されている場合は、以下が出力されます。

```json
{
    "IndexDocument": {
        "Suffix": "index.html"
    }
}
```

これで、対象の S3 バケットの静的 Web ホスティングが有効化されました。

ちなみに、有効化されていない場合は、以下が出力されます。

```sh
An error occurred (NoSuchWebsiteConfiguration) when calling the GetBucketWebsite operation: The specified bucket does not have a website configuration
```

### でも、実は・・・

本記事では、東京リージョン(ap-northeast-1)にバケットを作成しているので、以下のURLでアクセスできるようになります。

> http://\<BUCKETNAME\>.s3-website-ap-northeast-1.amazonaws.com

しかし、このままではアクセスできないのです。

試しに、curl コマンドを使って上述のURLにアクセスしてみます。

```sh
# 同じシェルをそのまま使える場合は環境変数を使う
curl http://${BUCKETNAME}.s3-website-ap-northeast-1.amazonaws.com/

# 閉じてしまったなどで使えない場合は、バケット名を自分で指定してください。
#curl http://<BUCKETNAME>.s3-website-ap-northeast-1.amazonaws.com/
```

すると、以下の様に、HTTP403 Forbidden が返されます。

```HTML
<html>
<head><title>403 Forbidden</title></head>
<body>
<h1>403 Forbidden</h1>
<ul>
<li>Code: AccessDenied</li>
<li>Message: Access Denied</li>
<li>RequestId: **************</li>
<li>HostId: ******************************************************</li>
</ul>
<hr/>
</body>
</html>
```

これを打開するには、次に実施するコンテンツの公開が必要です。

## コンテンツを公開する
というわけで、コンテンツの公開を行います。
s3api put-object-acl コマンドを実行します

```sh
# 同じシェルをそのまま使える場合は環境変数を使う
# コンテンツのファイル名が異なる場合は適宜変更する
aws s3api put-object-acl --bucket ${BUCKETNAME} --key index.html --acl public-read

# 閉じてしまったなどで使えない場合は、バケット名を自分で指定してください。
#aws s3api put-object-acl --bucket <BUCKETNAME> --key index.html --acl public-read
```

このコマンドも特に応答なく完了します。
実行できたら、Webブラウザでアクセス・・・もいいですが、 やはり、curl コマンドで HTML ファイルが表示されるか確認します。

```sh
# 同じシェルをそのまま使える場合は環境変数を使う
curl http://${BUCKETNAME}.s3-website-ap-northeast-1.amazonaws.com/

# 閉じてしまったなどで使えない場合は、バケット名を自分で指定してください。
#curl http://<BUCKETNAME>.s3-website-ap-northeast-1.amazonaws.com/
```

すると、以下の様に、作成した HTML ファイルの内容が出力されます。

```HTML
<!DOCTYPE html>
<html lang="ja">
<head>
  <title>Advent calendar 2021</title>
</head>
<body>
  <h1>Hello world!!</h1>
</body>
</html>
```

AWS CLI (とシェル)だけで Webサイトを構築することができました！

# まとめ
とりあえず、「Web サーバをさくっとたてるよ！」という目標は達成できました。
しかし、このままだと色々と問題があります、2日目以降でそのあたりに触れていきます。

* 今回使ったコマンド
 * s3api create-bucket
 * s3 cp
 * s3 ls
 * s3 website
 * s3api get-bucket-website
 * s3api put-object-acl