🐼

App RunnerとGithub Actionsで自動デプロイ環境を構築する

2021/08/02に公開

前回までのお話

前回は、App RunnerにNext.jsをdeployしました。
https://zenn.dev/program_panda/articles/488bf97fd0197c

やりたいこと

今回やりたいことは、CD環境の構築です。具体的に言うと、masterブランチにpush(or merge)されると、ECRにイメージを自動pushしたいと思いました。
App RunnerはECRへのpushを検知すると、自動デプロイが走る設定をボタン一つで実現できるので、後述するGithub ActionsとApp Runnerを組み合わせて、お手軽にCD環境の構築が可能です。素敵。

Github Actionsについて

簡単にいうと、Githubにデフォルトで付いているサービスで、GitHubだけでCI/CD的な機能を実現できます。無料枠がかなりでかいので、とてもおすすめです。(公式ソースを見たわけではないですが、執筆時点でpublicリポジトリなら、ずっと無料。privateリポジトリは月2000分まで無料です。安い)

参考記事

Github Actionsについては、ほぼこの記事通りにできました。感謝。が、今回はそれ以外の部分でハマったので、備忘録を兼ねて記事にまとめています。

参考: GithubActionでmasterプッシュ時にECRにimageをpushする
https://qiita.com/takehanKosuke/items/306be392421c6e0a1764

ECRにリポジトリを作成

こちらは前回までに作成済み。
話の本筋とは逸れますが、イメージスキャンの設定で、push時にスキャンを有効にしておくと、pushの度に脆弱性をチェックしてくれるようです。しかも無料。便利。
公式読んでる感じ、暗号化設定で、KMS 暗号化も有効にするとセキュリティー的に良いと思ったので、有効化しました。

参考: 【超待望アップデート】ECRに対する脆弱性スキャン機能が提供されました
https://dev.classmethod.jp/articles/ecr-repository-scan/

参考: ECR が AWS KMS キーを使用したイメージの暗号化をサポート(公式)
https://aws.amazon.com/jp/about-aws/whats-new/2020/07/ecr-supports-encryption-images-aws-kms-keys/

Github Actionsを動かすアクセスキー、シークレットキーを取得

参考記事通りですが、下記の手順を踏みます。

1、awsコンソールにログイン
2、検索窓から「iam」と検索
3、ユーザー追加をクリック
4.名前に「github-actions」(名前は任意の名前)アクセスの種類は「プログラムによるアクセス」にチェックして次へ
5.「既存のポリシーを直接アタッチ」を選択→「AmazonEC2ContainerRegistryPowerUser」と検索すると権限が出てくるのでこちらをチェック
6.あとは全て次へ。アクセスキーとシークレットキーをメモしておく。

補足ですが、今回はユーザーを作成して、ユーザーに対して既存のポリシーを直接アタッチしてますが、公式を読む限り、ユーザーグループを使用して、グループに対してポリシーをアタッチする方が望ましいのかもしれません。個人的にIAMは苦手意識があり、まだまだ勉強不足なので、ご意見あれば教えていただきたいです。

[公式] IAM ユーザーにアクセス許可を割り当てるためには、ユーザーグループを使用する
https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/best-practices.html#use-groups-for-permissions

Githubにシークレットキーを登録

参考記事通りですが、下記の手順を踏みます。
(ここまで参考記事通りすぎて、書いてて申し訳ないです。。)

1、githubの該当のリポジトリにいき下記3つの変数を追加する
AWS_ACCESS_KEY_ID(取得したアクセスキー)
AWS_SECRET_ACCESS_KEY(取得したシークレットキー)
AWS_ECR_REPO_NAME(ECRで作成したリポジトリ名)
上記のように変数を指定することで${{ secrets.キー名 }}とすることでその環境変数を使用できます。

Github Actionsのymlを作成

参考記事通りですが、下記の通り。
一点補足しておくと、Github Actionsを作成したことがない方は馴染みがないかもしれませんが、ルートプロジェクト直下に.githubディレクトリを作成して、直下にworkflowsディレクトリを作成。その直下にymlファイルを作成すると、yml内に定義した処理を実行できます。参考記事がとても丁寧でわかりやすいので、是非一読してみてください。

参考: GitHubの新機能「GitHub Actions」で試すCI/CD
https://knowledge.sakura.ad.jp/23478/

.github/workflows/config.yml
name: Build and Push

on:
  push:
    branches:
      - master

jobs:
  build-and-push:
    runs-on: ubuntu-18.04
    timeout-minutes: 300

    steps:
      - uses: actions/checkout@v1

      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ap-northeast-1

      - name: Login to Amazon ECR
        id: login-ecr
        uses: aws-actions/amazon-ecr-login@v1

      - name: Build, tag, and push image to Amazon ECR
        env:
          ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
          ECR_REPOSITORY: ${{ secrets.AWS_ECR_REPO_NAME }}
        run: |
          docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:latest .
          docker push $ECR_REGISTRY/$ECR_REPOSITORY:latest

masterにpush

実際にmasterにpushします。
Githubの Actionsタブを見てみると、処理が走っていることが確認できます。

ECRも見てみましょう。
ECR > リポジトリから、該当のリポジトリクリック。

良さそうです。

App Runnerをチェック。
App Runner > サービス > サービス名から、デフォルトドメインを確認すると反映されて...ない???

ハマったところ

結論的に言うと、Dockerfileが良くなかったです。元々は、ビルドをしていないイメージをpushして、開始コマンドでビルドをしていました。
App Runnerはデフォルトでアプリケーションログを出してくれるようになっていて、そちらを確認してみると下記のようなエラーが出てました。
It looks like you're trying to use TypeScript but do not have the required package(s) installed.
下記記事を読んでいると、ビルドを事前にしてイメージpushすればよいのではないかと思い、実行すると成功しました。
参考記事: Asked to install Typescript when already installed when building Docker image

https://stackoverflow.com/questions/59682961/asked-to-install-typescript-when-already-installed-when-building-docker-image

(App Runner > サービス > サービス名)

修正したDockerfileはこちら

Dockerfile
From node:14-alpine

# ワーキングディレクトリの指定
WORKDIR /usr/src/app

# linux Update, set Timezone, install bash
RUN apk --update add tzdata && \
    cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \
    apk del tzdata && \
    apk add --no-cache bash

# コピー & ペースト
COPY ./app /usr/src/app

# npm update & install & build
RUN npm install -g npm && \
    npm run remove && \
    npm install && \
    npm run build

package.jsonはこちら

package.json
"scripts": {
    "dev": "cross-env NODE_ENV=development node server/index.js",
    "build": "next build",
    "start": "cross-env NODE_ENV=production node server/index.js",
    "remove": "rm -rf node_modules && npm run clear:hard-source-cache",
    "clear:hard-source-cache": "rm -rf node_modules/.cache/hard-source/",
    "type-check": "tsc --pretty --noEmit",
    "format": "prettier --write **/*.{js,ts,tsx}",
    "lint": "eslint . --ext ts --ext tsx --ext js",
    "lintfix": "eslint --fix . --ext ts --ext tsx --ext js",
    "test": "jest",
    "test-all": "npm run lint && npm run type-check && npm run test"
  },

開始コマンドは、npm run startのみにしました。
(App Runner > サービス > サービス名の設定タブ)

こちらでmasterにpushしたところ、無事変更の反映が確認できました。

まとめ

App RunnerとGithub Actionsを使うと、非常にお手軽にCD環境を構築できます。
今回Github Actionsをはじめて使いましたが、Github Actionsについては、特段ハマることもなく、無料枠も大きくて非常に強力なサービスだなと思いました。
次は、Mongo DBとの接続を試していきます。

Discussion