はじめに
ストレージサービスとして有名&優秀なAmazon S3ですが、実は「静的ウェブサイトホスティング」という機能を使うことで、Vue.jsやReactで作ったSPAを簡単に公開することができます。また、AWS CLI を使用することでコマンド一発でサクッとデプロイすることができます。herokuやfirebaseなどのPaaSが充実している昨今、あまりS3でやるメリットない気もしますが。今回はその手順についてまとめてみました。
(ちなみに私がVue.jsをよく使うのでちょくちょくVue.jsが登場しますが、Reactでも同様の操作ができるはずなので、適宜読み替えていただければと思います。)
お値段
まず一番大事なお金の話から。
S3の料金は「利用したストレージの容量」「リクエスト件数」「リクエストに対するデータ送信量」の3軸で計算されます。
ストレージ料金 | |
---|---|
最初の 50 TB/月 | 0.025USD/GB |
リクエスト料金 | |
---|---|
PUT、COPY、POST、または LIST リクエスト | リクエスト 1,000 件あたり 0.0047USD |
GET、SELECT および他のすべてのリクエスト | リクエスト 1,000 件あたり 0.00037USD |
データ転送料金 | |
---|---|
1 GB まで/月 | 0.00USD/GB |
次の 9.999 TB/月 | 0.114USD/GB |
※料金 - Amazon S3 | AWSより一部抜粋
例えば、配信するコンテンツのデータサイズが1MB、リクエスト件数が100件/日の場合、
ストレージ料金:0.000025USD
リクエスト料金:0.00111USD
データ転送料金:0.228USD
で、合計約 0.229USD/月 (日本円で約 25.19円/月)です。ばちくそ安いですね。
アカウント開設から1年以内の無料枠を利用すればほぼ0円に抑えられると思います。
※参考 - AWS クラウド無料利用枠
SPAの準備
各フレームワークでのビルドを実行し、
index.html
と各フォルダ(css/js/img等)が揃っている状態にしましょう。
ちなみにVue.jsでのプロジェクト開始方法およびビルド方法はこちらの記事(Vue CLI スタートガイド)にまとめてありますので、フロントフレームワークを全く触ったことないという方はこちらを参考にしてみてください。
S3用のIAMユーザ作成
AWSルートアカウントの作成
AWSを初めて使うという方はAWSルートアカウントを作成しましょう。
こちらを参考にすると良いと思います。
AWS アカウント作成の流れ | AWS
S3用のIAMユーザの作成
ルートアカウントは全権限アカウントのため全てのAWSリソースへのアクセスができてしまいます。このルートアカウントで作業を続けることはセキュリティ上よろしくないので、S3のみ使用可能なIAMユーザを別途作成し、今後の作業はこのS3用IAMユーザで行います。
まずルートアカウントでログインし、マネジメントコンソールからIAMへ移動します(検索バーで「iam」と打てば出てきます)。
「ユーザー」メニューを選択すると、作成したIAMユーザの一覧が表示されます。
今回は新規でユーザを作成するので、青色ボタンの「ユーザーを追加」をクリックしましょう。
IAMユーザを作成するための設定画面が表示されます。
- ユーザー名は任意の名前で構いません(公開しようとしているSPA用のIAMユーザであることが分かるネーミングだと良いです)
それ以外はデフォルトの設定で問題ありません。
IAMユーザの作成が完了すると一覧に表示されるので、問題なく作成されているか確認しましょう。
IAMユーザの作成が完了したら、早速ログインしてみましょう。
右上にIAMユーザ名 @ アカウント名
と表示されていれば問題なくログインできています。
S3以外のサービスへのアクセスがブロックされているか確認するために、試しにIAMを開いてみましょう。
先ほどIAMユーザを作成した画面に移動しても「アクセス権限が必要です」と表示され、ユーザを新規作成できないようになっているはずです。
このように、利用用途ごとにIAMユーザを作成してAWSサービスへの権限を切り分け、意図しない操作が実行されないようにしましょう。
S3でSPAを公開
先ほどログインしたS3用IAMユーザで作業を進めます。
バケットの作成
S3の画面へ移動し、青色の「+バケットを作成する」ボタンをクリックしましょう。
バケット作成に際しての設定画面が表示されるので、情報を入力しましょう。
- バケット名:任意の文字で構いません。ここで設定したバケット名が後ほど静的ホスティングする際のURLの一部として使われるので、それっぽい名前を付けましょう。
- リージョン:これも任意で構いませんが、「アジアパシフィック(東京)」を選択するのが無難です。
それ以外の設定は一旦デフォルトのままで問題ないです。
バケットが作成されるとバケット一覧に表示されるようになります。
コンテンツのアップロード
バケット名をクリックするとバケットの詳細画面に遷移することができます。
青色の「アップロード」ボタンをクリックし、公開したいSPAの各ファイル(index.htmlとcss/js/imgフォルダ等)をローカルからアップロードしましょう。
初回アップロード時にバケットの設定について色々と聞かれますが、全てデフォルトで問題ないです。
無事アップロードが完了するとこのような画面になると思います。
静的ウェブサイトホスティング機能の設定
「プロパティ」タブへ移動し、「Static website hosting」の設定を行います。
上記の設定が完了したら「保存」ボタンをクリックしましょう。
なお、この画面で表示されている「エンドポイント」のURLがウェブサイトへのアクセス用URLになります。が、今の状態でこのURLにアクセスしようとしても403エラーが返ってきてしまいます。URLでのアクセスを許可するために、次の章で説明するバケットポリシーを設定しましょう。
バケットポリシーの設定
S3に格納したオブジェクトが不用意にネットに晒されないよう、デフォルトでは外部からS3バケットへのアクセスは全て拒否するようになっています。先ほど403エラーが返ってきたのもそのためです。正しくWebページを表示させるためにはURLによる外部からのリクエストを明示的に許可する必要があります。
アクセス制御に関することは「アクセス制御」タブで行います。
まず、「ブロックパブリックアクセス」を開きます。「編集」をクリックし、以下の設定を行います。
- 「パブリックアクセスをすべてブロック」のチェックを外します
- 下から2つ目、「新しいパブリックバケットポリシーを介して...」のチェックを外します
- 一番下、「任意のパブリックバケットポリシーを介して...」のチェックを外します
これでバケットポリシーによるアクセス許可設定が有効になります。ここの設定を行わないと、いくらバケットポリシーで許可の設定を行ってもブロックされてしまうので注意しましょう。
次に「バケットポリシー」を開き、エディタ欄に以下のJSONをバケット名を置き換えて貼り付けましょう。
このJSONはsample-hosting-kiyokiyo
バケットへのGetリクエストを許可するバケットポリシーです。AWS公式チュートリアルのものをそのまま抜粋しました。バケット名の部分のみ、自分が作成したバケット名に置き換えるのを忘れないようにしましょう。
{
"Version":"2012-10-17",
"Statement":[{
"Sid":"PublicReadForGetBucketObjects",
"Effect":"Allow",
"Principal": "*",
"Action":["s3:GetObject"],
"Resource":["arn:aws:s3:::sample-hosting-kiyokiyo/*"
]
}
]
}
これで外部からS3に格納したファイルを取得できるようになりました。
先ほど403エラーが返ってきたURLでアクセスし直すと、今度は正しくWebページが表示されるようになっているはずです。
S3へのデプロイコマンドを作る
上記の手順でWebページの公開はできるようになりましたが、Webページを更新するたびにIAMユーザでログインし、S3バケットに格納してあるファイルを削除して、ローカルにある新しいファイルをアップロードし直す、というのはかなり面倒です。Vue.jsでは
npm run serve
でローカルサーバーを起動し、
npm run build
でビルドを行うことができます。
それと同じノリで、
npm run deploy
で、S3へのデプロイができるよう設定を組みましょう。
AWS CLI を使用する
AWS CLI を使うと、ターミナル等のコマンドラインツールからAWSサービスを操作できるようになります。これを利用して、S3上の対象バケットにあるファイルを削除し、ローカルにある新規ファイルをアップロードするスクリプトを組みます。
こちらの記事でAWS CLI を使うための手順がまとめられているので参考にしてみてください。
【初心者向け】MacユーザがAWS CLIを最速で試す方法 | Developers.IO
かいつまんで説明しますと、
1:まずpipをインストールします(Python3.4以降であればPythonのインストールと同時に使えるそうです)。pip -V
と打ってバージョンが表示されれば問題ないです。
$ pip -V
pip 19.3.1 from /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/pip (python 3.7)
2:次にAWS CLI をインストールします
$ pip install awscli
3: ルートアカウントでS3用IAMユーザのアクセスキーとシークレットアクセスキーを生成・取得します。IAMメニューで先ほど作成したS3用IAMユーザを選択し、「認証情報」タブの「アクセスキーの作成」ボタンをクリックします。アクセスキーとシークレットアクセスキーが表示されるので、手元に控えておきましょう。
4:ターミナルにaws configure
と入力しS3を操作するための設定を行います。Access Key ID
とSecret Access Key
に先ほど取得した情報を入力しましょう。Default region
はS3バケットで指定したリージョン(アジアパシフィック(東京)の場合はap-northeast-1)を入力しましょう。Default output format
はとりあえずtextで問題ありません。
$ aws configure
AWS Access Key ID [None]: XXXX
AWS Secret Access Key [None]: XXXXXXXX
Default region name [None]: ap-northeast-1
Default output format [None]: text
動作確認として、aws s3 ls
でS3に登録しているバケットが一覧表示されればOKです。
$ aws s3 ls
2019-11-11 22:45:22 sample-hosting-kiyokiyo
デプロイ用のシェルスクリプトを組む
index.html等が格納されているディレクトリをdist
とします。
distと同じ階層にデプロイ用のスクリプトを記載したdeploy-s3.sh
を配置します。
ディレクトリ構造のイメージはこんな感じです。
(any directory)
├dist/
│ ├css/
│ ├img/
│ ├js/
│ └index.html
└deploy-s3.sh
deploy-s3.sh
の中身はこんな感じで書きます。
#!/bin/sh
aws s3 rm s3://sample-hosting-kiyokiyo/ --recursive
aws s3 cp dist s3://sample-hosting-kiyokiyo/ --recursive
1行目はシェルスクリプトを走らせるためのおまじないです。詳しく知りたい方はこちらの記事(#!/bin/sh は ただのコメントじゃないよ! Shebangだよ!)とかが参考になると思います。
2行目ではsample-hosting-kiyokiyoバケットの中身を再帰的(--recursive)に削除(rm)しています。
3行目ではdistディレクトリの中身をsample-hosting-kiyokiyoバケットにコピー(cp)しています。
AWS CLI でできることはこちらのAWS CLI Command Referenceにまとまっているので、他のスクリプトを走らせたい方は調べてみてください。
デプロイ用コマンドを作る
最後に、npm run deploy
と入力したら先ほど作成したdeploy-s3.sh
が呼び出されるようにします。
npm runコマンドはpackage.json
のscripts
ブロックで設定できます。
"deploy": "bash deploy-s3.sh"
をscriptsブロック内に追加しましょう。
{
(省略)
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint",
"deploy": "bash deploy-s3.sh"
},
(省略)
}
これで作業としては完了です。
試しにローカルでの変更をS3にデプロイできるか確かめてみましょう。
まず、ローカルで適当に変更を行います。
サンプルとして今回はとりあえずApp.vueのHelloWorldタグを以下のように変えてみます。
(変更前)
<HelloWorld msg="Welcome to Your Vue.js App"/>
(変更後)
<HelloWorld msg="Hi! My name is Kiyokiyo! Nice to meet you!"/>
ビルドコマンドを走らせます。
$ npm run build
これでローカルのdistディレクトリ以下に必要なファイルが揃いました。
最後にデプロイコマンドを走らせます。
$ npm run deploy
S3上のファイルがdeleteされ、ローカルのファイルがS3にアップロードされたことが、ターミナルの出力からも分かると思います。
WebページのURLにアクセスするとしっかり変更が反映されていますね。
おわりに
これでローカルで作成していた静的ウェブサイトを公開できるようになりました。
デプロイもコマンド一発で簡単にできるようになったので、開発速度もかなり向上したんじゃないでしょうか。
個人的な今後としては、LambdaやDynamoDBを利用したサーバーレスAPIとの通信にチャレンジしてみたいと思います。