静的サイトをGithub ActionsでAWS S3にデプロイする


AWSでの静的サイト配信に興味があり、連休で時間あったのでこのサイトをNetlifyからS3 + CloudFrontに苦労して移行してみました。

"Lighthouseの結果"

環境で変化があるか確認したかったので、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には直接アクセスできないようにパブリックアクセスは全てブロックしてください。

"パブリックアクセス禁止のS3"

作成したバケットのARNを、ポリシー作成時に使用しますので確認できる状態で次に進みます。

"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%失敗します。

注意点

  1. nodeバージョン

ローカルでbuildが成功したバージョンに揃えるのが良いです。12にしていますが必要に応じて変更してください。

  1. build後のフォルダ

yarn buildした時に作成される一般公開用のフォルダがpublicでないなら変更が必要です。例えばdistのパターンなら./publicではなく./distになります。ローカルでbuildした時にできるフォルダがpublicならそのままです。

  1. region

東京のリージョンで作成していない場合は、aws-regionを適切なものに変更してください。

secretsの登録

main.yamlを作成するとactionsが自動で走り、AWSのステップで失敗します。S3にデプロイするユーザー情報を登録し、成功するようにします。TEST_AWS_ACCESS_KEY_IDやTEST_AWS_SECRET_ACCESS_KEYはコード上に表記してはいけないためsettingsのsecretsに登録します。

"secret"

ユーザー作成時にダウンロードしたcsvファイルなどにaccess_keyとsecret_access_keyは表記されています。紛失した場合はAWSでユーザーのキー再生成が必要です。

secretsを登録したらactionsを再度動かし、全てのactionが成功したことを確認します。成功しなければ何か間違っているので適時修正します。全て成功すると、buildファイルがs3にコピーされます。

これで、masterブランチに変更が入るたびに自動的にbuildしてS3にファイルがデプロイされるようになりました。

次の記事ではS3にデプロイしたファイルをCloudFrontで配信を紹介します(記事製作中、今このサイトはS3で動いているので処理自体は完成しています)