NetlifyのサイトをAWSに移行するためにしたこと
背景
Netlifyの無料アカウントに個人サイトを置いていましたが、読み込みにやや時間がかかることが多くなっていました。
調べると、少なくとも無料アカウントの場合は、日本国内からの最寄りのサーバはシンガポールになってしまう[1]ようなので、S3 + CloudFrontベースに移行してみることにしました。
前提
GitHubにGatsbyJSのコードを置いており、一部のコンテンツはPrismicから更新をかけています。PrismicからWebhookでNetlifyのリビルドがかかるようになっていました。
行ったこと
移行後の構成は以下の通りです。
S3のバケットの準備
S3のバケットを準備します。
このとき、 パブリックアクセスをブロックする設定は全てオフ にしておきます。オンになっていると、gatsby-plugin-s3 からのデプロイに失敗したり、デプロイできたとしてもWebアクセスできなかったりします。
gatsby-plugin-s3の導入
gatsby-plugin-s3をインストールし、Gatsbyのガイド通りに設定を gatsby-config.js
に書き込んでおきます。
最終的にCodeBuildでビルドを自動化するのが目標ですので、 package.json
には --yes
オプション付きのコマンドを記載しておきます。
{
"scripts": {
"deploy": "gatsby-plugin-s3 deploy --yes"
}
}
buildspecの作成
CodeBuild用の buildspec.yml
を作成しておきます。
version: 0.2
phases:
install:
runtime-versions:
nodejs: 14
pre_build:
commands:
- npm install
build:
commands:
- npm run build
post_build:
commands:
- npm run deploy
CodePipelineとCodeBuildの作成
GitHubからソースコードを取り込むようにしてCodePipelineとCodeBuildを作成します。
CodeBuildのイメージはCodeBuildのユーザーガイドを見て、使用しているnode.jsのバージョンに対応するものを選択します。
また、CodeBuildのサービスロールにS3への書き込み権限(AWS管理ポリシーであれば AmazonS3FullAccess
)を付与しておきます。
S3へのデプロイは、buildspecの post_build
で呼び出しているので、デプロイステージに関してはスキップとしておきます。
作成したら一度ビルドを実行しておきます。
CodeBuildを呼び出すLambda関数の作成
Webhook用に、CodeBuildを呼び出すLambda関数を作成しておきます。このLambda関数の実行ロールにCodeBuildのビルドを開始できる権限(AWS管理ポリシーであれば AWSCodeBuildDeveloperAccess
)を付与しておきます。
const AWS = require('aws-sdk');
const codeBuild = new AWS.CodeBuild();
const output = await (codeBuild.startBuild)({
projectName: 'YOUR_CODEBUILD_PROJECT_NAME',
}).promise();
また、上記のLambda関数を呼び出すAPI Gatewayのエンドポイントも作成しておき、そのURLをPrismic CMSのWebhook先に登録しておきます。
CloudFrontのディストリビューションを作成
CloudFrontのディストリビューションを作成し、Originを上記で作成したバケットのウェブサイトエンドポイントにしておきます。
これは、gatsby-plugin-s3が、 gatsby-node.js
で作成したリダイレクトや、 ディレクトリ名末尾の /
を省略したパスなどをリダイレクトルールとして自動的に登録しているためです。ウェブサイトエンドポイントを使わない場合はそのあたりの処理を自力で構築することになってしまいます。
ディストリビューションの作成が終わったらDNSのCNAMEを書き換えて表示確認をします。このとき403エラーが出る場合はパブリックアクセスの設定などを確認してください。
おわりに
予想はしていましたが、Netlifyの機能を自力で再現するとここまでの手順が必要になるということで、それがマネージドサービスとして提供されていることのありがたさを改めて思うところです。
Discussion