サイトを作り直した。
それに伴い、デプロイのフローも整備した。
具体的には CircleCI でビルドを行い、S3 へのアップロードや CloudFront のキャッシュのクリアまで行う。
ソースは全部公開してあるので参考にどうぞ。
github.com
前提として、予めサイトは S3 で公開済みであり、CloudFront からの配信、独自ドメインやHTTPSの設定も行ってあった。
なので今回行ったのは、コンテンツの作り直しと、手動で行われていた S3 へのアップロードやキャッシュのクリアの自動化。
CircleCI に入門する機会にしたいという目的もあった。
Gatsby
まずはコンテンツの作り直し。
Gatsbyで作成した。
Gatsby は、React を使ってスタティックなサイトをジェネレートするフレームワーク。
このスライドの説明が分かりやすいと思う。
作ったサイトはこれ。
https://numb86.net
ほとんど中身はないのでHTMLを直打ちしたほうが速いだろうが、Gatsby に触ってみるというのも目的の一つだったので問題ない。
何より、マークアップより React を書いているほうが楽しい。個人プロジェクトなのだから楽しさが重要。
まずはインストール。
$ npm i -g gatsby-cli
その後、プロジェクトを作成。とにかくシンプルに始めたかったので、スターターはhello-world
にした。
$ gatsby new numb86.net https://github.com/gatsbyjs/gatsby-starter-hello-world $ cd numb86.net
あとは、チュートリアルを参考にしてサイトを作っていく。
$ gatsby build
するとpublic
ディレクトリに成果物が出力される。
なので後はこのディレクトリの内容を S3 にアップロードすればいい。
サイト内容に問題がなければ次は、CircleCI を使ってビルドやデプロイを自動化する。
だがその前に、CircleCI が S3 へのアップロードを行えるよう、AWS の権限を設定する必要がある。
AWS IAM
AWS の認証や認可を操作するには、IAM という機能を使う。
まずは以下の内容のポリシーを作成。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "s3:*", "Resource": ["arn:aws:s3:::numb86.net", "arn:aws:s3:::numb86.net/*"] } ] }
次に、このポリシーを付与されたユーザーを作成する。
するとアクセスキーが生成されるので、それをメモしておく。
CircleCI
GitHub のアカウントで CircleCI にサインアップ。
Add Projects
で自分のリポジトリの一覧が表示されるので、対象のリポジトリを選択する。
Start building
をクリックするとCIが実行される。設定ファイルがないので失敗するが、CircleCI が実行されるのは確認できた。あとは設定を整えていけばいい。
まず、環境変数の設定。
CircleCI の設定画面で行えるので、AWS_ACCESS_KEY_ID
とAWS_SECRET_ACCESS_KEY
を登録する。値はそれぞれ、先程作成した IAM のアクセスキー。
次に、プロジェクト内に.circleci/config.yml
を作成する。これが設定ファイルになる。
version: 2 jobs: build: docker: - image: circleci/node:latest branches: only: master steps: - checkout - restore_cache: keys: - dependencies- # fallback to using the latest cache if no exact match is found - dependencies- - run: name: Install command: yarn install - save_cache: paths: - node_modules key: dependencies- - run: name: Gatsby build site command: yarn build - run: curl -L https://github.com/bep/s3deploy/releases/download/v2.2.0/s3deploy_2.2.0_Linux-64bit.tar.gz | tar xvz - run: name: deploy command: ./s3deploy -source=public/ -region=ap-northeast-1 -bucket=numb86.net
この状態でmaster
にコミットしてpush
すると、自動的に CircleCI が実行され、デプロイまで行われるはず。
デプロイにはs3deploy
というライブラリを使っている。
CloudFront Create Invalidation
コンテンツは CloudFront から配信しているので、デプロイ時にキャッシュのクリアも行うようにした。
まずは、IAM のポリシーを変更して、CloudFront も操作できるようにした。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "s3:*", "Resource": [ "arn:aws:s3:::numb86.net", "arn:aws:s3:::numb86.net/*" ] }, { "Effect": "Allow", "Action": [ "cloudfront:GetDistribution", "cloudfront:CreateInvalidation" ], "Resource": "*" } ] }
最初はこのドキュメントを参考にしてarn:aws:cloudfront::AWS_ACCOUNT_ID:distribution/DISTRIBUTION_ID
のようにリソースを指定しようとしたが、以下のメッセージが出てしまい断念。
ポリシーのアクションはリソースレベルのアクセス許可をサポートしておらず、 すべてのリソース を選択する必要があります
そのため"Resource": "*"
とした。
次に、CircleCI にCLOUDFRONT_DISTRIBUTION_ID
という環境変数を設定して、キャッシュのクリアを行うディストリビューションを指定する。
最後に、.circleci/config.yml
にキャッシュのクリアに関する記述を追加する。
- run: name: deploy - command: ./s3deploy -source=public/ -region=ap-northeast-1 -bucket=numb86.net + command: ./s3deploy -source=public/ -region=ap-northeast-1 + -distribution-id=$CLOUDFRONT_DISTRIBUTION_ID -bucket=numb86.net
これでmaster
にコミットしてpush
すれば、ビルド、デプロイ、キャッシュのクリアを全て、CircleCI が自動的に行われるはず。
しかもs3deploy
は優秀で、キャッシュのクリアが必要なときだけ、行ってくる。つまり配信されるコンテンツに変更がない場合はクリアを行わないという判断を、自動的に行なってくれる。
参考資料
- AWS再入門 AWS IAM (Identity and Access Management) 編 | DevelopersIO
- Automate Your Static Site Deployment with CircleCI | Forestry.io
- bep/s3deploy: A simple tool to deploy static websites to Amazon S3 and CloudFront with Gzip and custom headers support (e.g. "Cache-Control")
- How to use CircleCI for GitHub Pages Continuous Deployment