静的サイトをGithub ActionsでAWS S3にデプロイする
AWSでの静的サイト配信に興味があり、連休で時間あったのでこのサイトをNetlifyからS3 + CloudFrontに苦労して移行してみました。
環境で変化があるか確認したかったので、Netlifyの時のLighthouse。Performanceは良くありませんがこれはNetlifyというよりこのサイトの作りに原因があります。とはいえ、AWSでの配信はお金がかかりますのでサーバーの影響で少しは改善しないかなと期待。
書いていると長くなったので Github〜S3デプロイまでと、S3〜CloudFront配信までの2記事にしました。
注意点
※もし静的なサイトを公開する方法を探してこの記事にたどり着いた場合、例えばReactで作ったサンプルアプリやポートフォリオを公開したいだけならまずはNetlifyやFirebaseを個人的にはお勧めします。お手軽かつ無料だからです。
- この記事はAWS不慣れな人が書いています。
- S3 + CloudFront方式は有料です(従量課金)
Githubにprivateリポジトリを作成する
Githubにprivateリポジトリを作成し、配信する静的サイトのコードを登録します。練習の場合は適当にGatsbyのスターターやCreateReactAppなどを登録してください。作成するリポジトリは公開リポジトリでも構いませんがその場合はAWSユーザのキーの取扱いに注意が必要です(注意したくなかったのでprivateにしています)
Gatsbyで新規サイト作成 ※gatsby-cliはインストール済みなら必要ありません
npm install -g gatsby-cli
gatsby new gatsby-site https://github.com/gatsbyjs/gatsby-starter-hello-world
ローカル環境でHello Worldが表示されること、yarn buildがエラーなく終了するところまで確認したら次に進みます。
S3のバケット作成
静的サイトを配信するファイルの置き場所をAWSで作成します。バケット名はドメイン名など含める必要もなく何でも良く、S3には直接アクセスできないようにパブリックアクセスは全てブロックしてください。
作成したバケットのARNを、ポリシー作成時に使用しますので確認できる状態で次に進みます。
I AMユーザーの作成
GithubからS3へのアップロードを行える権限を持ったユーザーを作成します。AWS IAMへ行き該当権限のポリシーを作成します
ポリシーの作成
新規でポリシーを作成します。名前は何でも良いです。下記のポリシーのResourceのところに先ほど作成したS3のバケットARNをコピペします。AllObjectActionsの方はARN最後に/*付与してください
※このあたりどこかの情報をコピペしているので不必要な権限が入っている可能性あります。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ListObjectsInBucket",
"Effect": "Allow",
"Action": [
"s3:ListBucket"
],
"Resource": [
"arn~~~"
]
},
{
"Sid": "AllObjectActions",
"Effect": "Allow",
"Action": "s3:*Object",
"Resource": [
"arn:~~~/*"
]
}
]
}
ユーザー作成
ポリシー作成後、ユーザーを作成して上記作成のポリシーだけ付与します。ユーザーのアクセス権限はプログラムによるアクセスを指定。ユーザー作成が終了するとシークレットが表示されますのでメモするかcsvをダウンロードしておきます。このシークレット情報は自分以外に知られてはいけません。
Github Actionsの設定
Githubにコードをプッシュしたら先ほど作成したS3にファイルコピーするCI/CDを作成します。Github Actionsには一般ユーザーがマーケットに公開している機能もありますが、何となく怖かったのでGithubとAWSが提供しているactionのみ使用しました。
作成済みのGithubのリポジトリに行き、画面上部のActionsタブをクリック。setup a workflow yourselfを選択します。main.yamlの作成ページにいくので下記のようにします
このファイルに先ほどのsecretsを直接書かないように注意してください
# This is a basic workflow to help you get started with Actions
name: CI
# Controls when the action will run. Triggers the workflow on push or pull request
# events but only for the master branch
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "build"
deploy:
name: Build And Upload to S3
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Build
uses: actions/setup-node@v1
with:
node-version: '12'
- run: yarn
- run: yarn build
- name: Configure AWS credentials from account
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.TEST_AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.TEST_AWS_SECRET_ACCESS_KEY }}
aws-region: ap-northeast-1
- name: Copy Files to s3
run: |
aws s3 sync ./public s3://s3バケット名
参考:https://github.com/aws-actions/configure-aws-credentials
masterブランチに変化があったときにnode12の環境でライブラリがインストール(yarn)され、build(yarn build)されます。yarnではなくnpmが良ければ変更してください。次のステップで先ほど作成したAWSのユーザーでs3にbuildしたファイルをsyncします。
s3バケット名となっているところは自身で作成した先ほどのバケット名です。頭にs3://を付けます
aws s3 sync ./public s3://northeast-9d9dーーーー # こんな感じになります
この時点ではsecretsを登録していないのでactionは100%失敗します。
注意点
- nodeバージョン
ローカルでbuildが成功したバージョンに揃えるのが良いです。12にしていますが必要に応じて変更してください。
- build後のフォルダ
yarn buildした時に作成される一般公開用のフォルダがpublicでないなら変更が必要です。例えばdistのパターンなら./publicではなく./distになります。ローカルでbuildした時にできるフォルダがpublicならそのままです。
- region
東京のリージョンで作成していない場合は、aws-regionを適切なものに変更してください。
secretsの登録
main.yamlを作成するとactionsが自動で走り、AWSのステップで失敗します。S3にデプロイするユーザー情報を登録し、成功するようにします。TEST_AWS_ACCESS_KEY_IDやTEST_AWS_SECRET_ACCESS_KEYはコード上に表記してはいけないためsettingsのsecretsに登録します。
ユーザー作成時にダウンロードしたcsvファイルなどにaccess_keyとsecret_access_keyは表記されています。紛失した場合はAWSでユーザーのキー再生成が必要です。
secretsを登録したらactionsを再度動かし、全てのactionが成功したことを確認します。成功しなければ何か間違っているので適時修正します。全て成功すると、buildファイルがs3にコピーされます。
これで、masterブランチに変更が入るたびに自動的にbuildしてS3にファイルがデプロイされるようになりました。
次の記事ではS3にデプロイしたファイルをCloudFrontで配信を紹介します(記事製作中、今このサイトはS3で動いているので処理自体は完成しています)