じゅころぐAR

ARのブログ

Vue.jsで作ったWebサイトをAmazon S3+CloudFrontで公開する

先日Vue.jsで制作&公開したWebサイトは、AWSでお安く運営しています。

Vue.jsでWebサイトをサクッと作る - じゅころぐAR
Vue.jsで作ったサイトをPWAに対応させてみる - じゅころぐAR

構成はよくある"静的WebサイトのS3ホスティングパターン"ですが、必要な設定を全部まとめておきたかったので書きます。

f:id:jyuko49:20180428231806p:plain

構築手順

2018年4月時点の画面および手順です。
※Managed ConsoleのUIは頻繁に変わるので注意

独自ドメインを取得する

"Route53"を選択し、Domainsの"Register Domain"をクリックします。

f:id:jyuko49:20180428232738p:plain

希望のドメインを入力し、トップドメイン(.comなど)を選択して"Check"をクリックすると、取得可能なドメインが表示されます。

ドメインを決めたら"Add to cart"でカートに入れて、画面に従って購入します。

f:id:jyuko49:20180428234438p:plain

SSL/TLS証明書を取得する

WebサイトをHTTPSに対応させるため、SSL/TLS証明書を取得しておきます。AWS内での利用になりますが、無料で発行できます。

"Certificate Manager"を選択し、証明書のプロビジョニングを選びます。

f:id:jyuko49:20180429002916p:plain

証明書を発行したいドメインを入力します。Route53で取得したドメインに、*.を付けてワイルドカード証明書を発行します。
こうしておけば、サブドメイン全てで同じ証明書が利用でき、再発行等の手間が省けます。

f:id:jyuko49:20180429002936p:plain

S3バケットを作成する

"S3"を選択し、ファイルをアップするバケット(Bucket)を作成します。
バケット名は公開したいドメイン名にします。Route53で取得したドメイン(例: jyuko49.com)にサブドメインを追加したドメイン名(例: app.jyuko49.com)を入れます。
リージョンはロケーションが近い場所(東京)を選択した方がファイルアップの際の通信などで都合がよいです。

f:id:jyuko49:20180428235431p:plain

バケットを作成したら、ファイルをアップします。Vue.jsをwebpackでビルドして、/distに作られるファイルをまるっとアップします。

f:id:jyuko49:20180429000724p:plain

CloudFrontを設定する

"CloudFront"を選択して、"Create Distribution"をクリックします。

f:id:jyuko49:20180429012414p:plain

最初の選択肢は"Web"を選びます。表示される設定画面で、オリジン(Origin)に先程作成したS3バケットを選択します。

f:id:jyuko49:20180429001735p:plain

"Alternate Domain Names(CNAMEs)"S3バケット名にしたドメインと同じドメイン名を設定します。
あわせて、すぐ下の"SSL Certificate""Custom SSL Certificate"に変更し、Certificate Managerで作成したワイルドカード証明書を選択します。

f:id:jyuko49:20180429005525p:plain

その他の項目はお好みで。全てデフォルトのままでも問題ありません。

私が実際に設定したのは、ドメイン直下(パスなし)でアクセスした際の"Default Root Object"index.htmlにしたのと、

f:id:jyuko49:20180429012925p:plain

HTTPのリクエストをHTTPSにリダイレクトする設定(常時HTTPS化)です。

f:id:jyuko49:20180429013604p:plain

作成できたら"Domain Name"に表示されるURL(*****.cloudfront.net)をメモっておきます。次の手順で使います。

Route53にサブドメインを登録する

いよいよ最後の手順です。

"Route53"に戻って、"Hosted zones"から最初に設定したドメインを選択します。
メニューが開いたら"Create Record Set"をクリック。

Nameにサブドメインを入力します。S3バケット名とCloudFrontのCNAMEに設定したドメインのサブドメインです。
続いて、ValueCloudFrontディストリビューションのDomain Name(*.cloudfront.net)を入力します。
設定ができたら、"Create"でレコードが作成されます。

f:id:jyuko49:20180429013844p:plain

ここまで設定したら、ドメインにアクセスして表示ができているか確認しましょう。
Route53 → CloudFront → S3 とS3にアップされたコンテンツが参照され、HTTPS通信時はCloudFrontにてCertificate Managerで発行した証明書による認証が行われます。

S3アップ時に自動でCache Invaridationを行う

CloudFrontはS3にアップしたコンテンツをキャッシュするので、S3のファイルを更新した際にキャッシュが残っていると反映が遅れます。
"Invalidation"を行えばキャッシュが消えますが、毎回手動で行うのは手間なので、S3にファイルをアップしたら自動でInvalidationを行うようLambdaファンクションを設定しておきます。
Lambdaには常に有効な無料枠があるので、余程頻繁にファイルアップをしない限り、コスト負担はありません。

"Lambda"を選択して、"関数の作成"をクリックします。名称の他に、ランタイム(スクリプト)の言語とバージョン、IAMロールを入力する必要があります。

IAMロールとスクリプトは、以下の記事を参考にしました。
Automatic Cloudfront Invalidation With Amazon Lambda | Blog

スクリプトの用意ができたら、トリガーとしてS3を追加します。

f:id:jyuko49:20180429165956p:plain

Webサイト用に作成したバケットを選択して、"オブジェクトの作成(すべて)"をトリガーにします。

f:id:jyuko49:20180429170019p:plain

トリガーを保存してLambdaファンクションを有効にすれば、S3へのファイルアップ時、自動でキャッシュが消えるようになります。

請求アラートを設定する

アクセスが急増して請求額が増えたときに気付けるようアラートを設定しておきます。

"請求ダッシュボード"の設定メニューで請求アラートが有効になっていなければチェックして設定を保存します。

f:id:jyuko49:20180429172340p:plain

通知の設定は"Cloud Watch"で行います。
"アラームの作成"を行い、メトリクスに"概算合計請求額"を設定します。

f:id:jyuko49:20180429172505p:plain

アラームの名前を入力して、通知を行う金額を設定します。コスト感は後述しますが、想定の利用料は$5にも満たないので、$5を超えたらメールが来るようにしました。

f:id:jyuko49:20180429173418p:plain

請求アラートはその金額を超えたときに1回のみの通知なので、通知する金額を段階的に変えて、複数のアラートを設定するのも手です。


かなり長くなりましたが、ここまで設定しておけば、Webサイトとして実運用に耐えうるレベルかなと思っています。

まだ未対応の作業としては、"ローカルマシンからS3へのアップロードを自動化するwebpackのプラグイン"を追加すれば、サイトの更新がさらに楽になるので導入を検討中です。

github.com

メリット

機能面

CloudFrontを導入していることで、

  • 常時HTTPS
  • HTTP/2
  • キャッシュによる高速化(CDN)

が有効になります。

HTTPSでセキュアな通信を行いつつ、HTTP/2とCDNの効果でクライアントとの通信遅延も抑えられるため、Webサイトの品質も向上します。

また、サーバレスの構成なので、サーバの高負荷や遅延に悩むこともありません。特定の時間帯にアクセスが急増したとしても耐えられます。
その分、課金はされますが、アラートも設定していますし、金額的には誤差の範囲に収まるかと思います。

コスト面

まず、ドメインの取得に年額$12.0かかっています。1ヶ月あたり100円くらいですね。取得したドメイン名によって金額は異なります。
また、Route53でホストゾーン1つに$0.5かかります。

S3にファイルを配置する料金は1GBあたり$0.025で、仮に1GB使ったとしても月額3円程度です。今回制作したサイトは画像を含めても15MB以下なので1円もかかりません。

費用として見込んでおく必要があるのは、Webサイト閲覧時のファイルダウンロードにかかる通信料です。
CloudFrontでは$0.14/GBで、ページサイズが1MBなら1000PVで1GB=$0.14の計算になります。個人サイトなら月間のPVはそこまで多くないので、実際には100円以下の請求です。

合計しても、数百円/月で運営できています。

実際に4月の請求額からドメイン取得にかかった費用($12+税)を除くと、$1もかかっていません。

f:id:jyuko49:20180429174927p:plain

f:id:jyuko49:20180429175416p:plain

まとめ

Webサイト用にわざわざインスタンスを立てるより管理が楽ですし、機能・コストのどちらを取ってもオススメの構成です。
サーバがないのでSSRとかは難しいかもしれませんが、非同期処理はAPI Gateway + LambdaのサーバレスAPIと組み合わせれば実現できるので拡張性もそこそこあります。