Amplify Hostingの中身が気になってS3+Cloudfront+CodeBuildで静的ホスティングをした
はじめに
私は、TypeScriptでアプリケーション開発をしているエンジニアです。(特にフロントが得意)
よくAWSのAmplify Hostingを利用することがあるのですが、何もせずインフラが構築できるため、Amplify Hostingが何をしているのか理解したくなりました。
そこでまずは、一番簡単そうな静的ホスティングを試してみようと思います。Next.jsのアプリケーションを静的ビルドして、AWSにあげます。
はじめに言っておきますが、車輪の再発明な感じ(Amplify hHsting使えば一瞬で終わること)なので、Amplify使った方が良いと思います。
フロントエンドエンジニアがはじめてAWSを使って何かしたいって思った時におすすめの記事です。
S3+Cloudfront構成
なぜS3か
S3(Amazon Simple Storage Service)とは、静的なサイトや画像、バックアップデータなどが保存できるストレージサービスです。
99.9999999% (イレブンナイン) の耐久性と、99.9% の可用性ががあるので、安定・安全に利用することができるため人気です。(利用料も高くない)
私は、SSGしたサイトやSPAアプリケーションを置いたり、アプリケーション内で投稿された画像などを保持して置く場所として使うことが多いです。
なぜCloudfront構成か
Cloudfrontとは、いわゆるCDNで、コンテンツを高速で配信してくれるものです。
エッジロケーションを経由してコンテンツを配信しますので、ユーザーがアクセスする場所から近いところからコンテンツを配信します。
わかりやすくいうと、日本・アメリカ・その他国々(実際はもっと細かく分類されている)など世界各地で置かれているサーバーそれぞれにコンテンツを保持しておいて、ユーザーが日本でアクセスしたら日本のサーバーから配信する。アメリカからアクセスしたらアメリカのサーバーから配信する。などして、接続スピードの高速化や、個々のサーバーの負担を減らすことができます。
サイトの読み込み速度と、負荷への耐久性が向上できます。
実際にやってみる
実際にこの構成の環境を構築します。
S3
特筆するところのみ、記載しております。記載のないものはデフォルトでOKです。
バケット作成
ACLを無効にする/パブリックアクセスをブロック
ACL(アクセスコントロールリスト)を無効にします。
ACLはレガシーな方法なので、AWSが無効にすることを推奨しております。
Cloudfrontからのアクセスのみ許可したいので、パブリックアクセスをブロックします。
バケットのバージョニング/暗号化方法はSSE-S3
バケットのバージョン管理ができるみたいですが、特に使う必要がないので無効にします。
暗号化の方法は3通りありますが、SSE-S3がデフォルトになっております。
SSE-S3以外の方法は、より細かい設定ができるが費用は高くなると言った方法なので、今回わざわざ使うこともないです。
S3バケットにファイルをアップロードする
バケット内にファイルをアップロードできます。
アップロードボタンからファイルやフォルダを選択してアップロードします。
ただ、どうせならアップロードを自動化したい(例えばgithubで特定ブランチにマージされたタイミングで)ので、この記事の後半でCodeBuildを使ってみます。
Cloudfront
distribution作成
オリジン・名前・オリジンアクセスの設定
オリジンは、Cloudfrontで接続する先を指定しますが、今回は先ほど作ったS3のバケットになります。
名前は適当なものを入力してください。
オリジンアクセスは、Origin access control settingsにしてください。Cloudfrontからのアクセスのみ許可するためです。
OAC作成/設定
OACとは、オリジンアクセスコントロールの略で、CloudFrontからS3へのアクセス権限を設定しようというようなものです。
OAIという設定方法もあるようですがこれはレガシーな方法で、OACで設定するのが一般的です。
以下のように作成して、それを設定します。
WAF/料金クラス設定
WAFはセキュリティ対策で設定するものですが、今回は個人で利用するためなるべくコストをかけたくありません。無効にします。
料金クラスは、日本のサーバーが使えればOKなので以下を設定。
エッジロケーションで利用できるエリアを設定できます。エリアが多いと高くなります(多分)
HTTP2を設定/デフォルトルートオブジェクトを入力
HTTP2のみ設定します。
デフォルトルートオブジェクトはトップページのファイルを指定します。
SSGやSPAの場合はルートディレクトリのindex.htmlになるかと思います。
筆者は初め、デフォルトルートオブジェクトを入力していなかったため、サイトが表示されずに少し詰まりました。
作成成功 ポリシーをコピーする
黄色で出てくるメッセージ内のポリシーをコピーします。S3側でポリシー設定をして、このディストリビューションが該当のS3にアクセスできるようにします。
S3のバケットポリシー設定
Cloudfrontからコピーしてきたものをペーストしてください。バケットポリシーの編集ボタンをクリックして、エディターみたいなものが出るのでそこにペーストします。
設定完了!URL確認
Cloudfrontのディストリビューション名がURLになっていますので、そのURLにアクセスします。
きちんと表示されていれば成功
一応、S3バケットに直アクセスができないか確認
403になっていればOK
デプロイ自動化
コードを更新するたびに、手動でbuildしてS3のバケットにアップするのは辛いですよね。
なので自動化しましょう。
CodeBuild
AWSのCodeBuildというものを使います。
CodeBuildは、CIサービスです。githubやbitbucketなどと繋げて、mergeやpushなどをhookに決まったコマンドを使うことができます。Dockerイメージを利用して起動しています。
S3のバケットにbuildしたファイルをアップロードすることができるので、それを今回やろうと思います。
設定方法
AWS ConsoleでCodeBuildを選択
プロジェクトを作成する
任意の名前を入力
Githubと接続する・自動デプロイしたいリポジトリ選択
ウェブフックイベント
単一ビルド
以下は、mainブランチにpush or プルリクマージをフックにしてイベントが走るようになる。
BuildSpec
CodeBuildの内容を定義する。
buildspec.ymlでリポジトリのファイルにコードで定義するので、以下のように設定
buildspec.ymlは以下になります。
version: 0.2
env:
variables:
ENV: 値を書く
phases:
# codebuildで使用するruntimeをinstall
install:
runtime-versions:
nodejs: 22
# アプリケーションのビルド前に行うコマンド
pre_build:
commands: npm install
# ビルド
build:
commands: npm run build
# ビルド後に行うコマンド ビルドしたものをS3の特定のバケットに置きます
post_build:
commands:
- aws s3 sync out/ s3://[bucket nameを入れる]/
アーティファクト/ログ
アーティファクトとは、ビルドされた成果物です。アーティファクトをどのように置くのか設定できますが、今回はbuildspec.ymlで、post_buildのタイミングでS3にsyncしているので、特に何も設定しません。
ちなみに、buildspec.ymlでartifactを設定するのが一般的なようです。今回artifactではどうしても上手くいかなかった(バケット直下にファイルを置けなくて、どうしてもバケット内にフォルダを作ってビルド成果物を置いてしまう)ため、post_buildを使いました。
ログを出さないとCodebuildの処理のログが見れないので、チェックしてください。
こちらで設定は完了です。buildspec.ymlをリポジトリに反映させれば、ウェブフックイベントが発火してCodebuildが動きます。
SSMのparameter storeを使って環境変数をセキュアに保持する
envをコードでベタ書きにするのは嫌なので、セキュアに環境変数を保持したくなりました。
社内のインフラエンジニアがparameter storeというのを使っていたのを思い出したので、調べつつやってみました。
parameter設定
systems managerを選択
サイドメニューからパラメータストアを選択
パラメータの作成
パスを含むファイル名とvalueを設定
buildspec.ymlのenvを書き換える
env:
parameter-store:
ENV: "/path/env_title"
IAMポリシーの更新
CodeBuildで設定した時に作られたポリシーに、SSMのread権限を加えます。
本当はインラインでjson書いて、parameter storeのみのread権限を与えた方が良いですが、時短したいので、ありもののポリシーを使いました。
AmazonSSMReadOnlyAccessというものを設定してます。
CodeBuildが動いてるか確認
設定したアクションをフックにして、CodeBuildを動かします。
成功したらOK
まとめ/学び
一番簡単そうな静的ホスティングを調べながらやってみましたが、結構スムーズに進みました。
なんとなくAWSでインフラ構築ができて楽しかったです。
また、普段自担当でない範囲も、MTG中耳を傾けていたり、コードを見あさるなどアンテナを張っていると、意外と頭に残っているなと思いました。今回Codebuildやparameter storeを使ったのはアンテナを張っていて名前と用途を少し覚えていたから。
これからも色々な技術に興味を持っていたいと思いました、、!
Discussion