Next.js製の自作ブログをAppRunnerにデプロイ
公開日:
はじめに
2022 年 9 月 24 日現在、このブログのホスティングは Vercel
に任せているんですが、Vercel
は無料利用の範囲が定められています。今回は、広告を貼りたい場合や、その他無料利用の枠をはみ出したい欲望に駆られた時のために、AWS を使ってデプロイする練習をしてみました。
具体的には、AWS のAppRunnerというサービスを利用しています。AppRunner
は、ソースコードの変更を検知して、自動的にデプロイする方法も選択できるらしいですが、今回は GitHubActions
と Docker
の勉強も兼ねたかったので、ECR を用いてデプロイしています。
デプロイのイメージは上の図の通りです。
ECR
には無料枠はあるのですが、その枠を超えるとストレージの容量によって課金されていきます。
ECR の料金
https://aws.amazon.com/jp/ecr/pricing/
なので、push するイメージの容量は小さいに越したことはありません。そこで今回は Next.js
の standaone モードというのを利用します。
Next.js の standalone モード
https://nextjs.org/docs/advanced-features/output-file-tracing#automatically-copying-traced-files
https://zenn.dev/team_zenn/articles/nextjs-standalone-mode-cloudrun
要約すると、Next.js
で standalone モードというのを有効にすることで、ビルド時に node_modules
の中から必要なファイルのみをコピーし、.next/standalone
以下に自動で保存してくれるため、.next/standalone
のみでアプリを動作させることができ、その結果ビルド後のサイズを大幅に削減することができる。というものらしいです。
せっかくなので、使います。
デプロイしてみる
docker イメージを作る
まずは ECR
に push するためのイメージを作るために Dockerfile
を書いていきます。
Dockerfile
# Install dependencies only when needed
FROM node:16-alpine AS deps
RUN apk add --no-cache libc6-compat
WORKDIR /app
COPY package.json ./
COPY yarn.lock ./
RUN yarn --frozen-lockfile
# Rebuild the source code only when needed
FROM node:16-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN yarn build
# Production image, copy all the files and run next
FROM node:16-alpine AS runner
WORKDIR /app
ENV NODE_ENV production
COPY --from=builder /app/public ./public
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
CMD ["node", "server.js"]
https://github.com/vercel/next.js/blob/canary/examples/with-docker/Dockerfile
公式の exampleを参考にしながら、上のような Dockerfile
を作ります。
- 依存関係の取得
- ビルド
- サーバーの起動
の 3 つのステージに分けてマルチステージビルドを用いて 1 つの Dockerfile
でまとめました
公式ドキュメントの他には下のブログを参考にしています。
https://zenn.dev/team_zenn/articles/nextjs-standalone-mode-cloudrun
手元で動作確認
ローカル環境でイメージを作成し、そのイメージを動作確認します。
docker build -t test .
test という名前でイメージを作成!
docker run -p 3000:3000 test
3000 番ポートでアプリを起動!
localhost:3000 でブラウザからアクセスできる!
ECR のリポジトリの作成
イメージを push するために、ECR
のリポジトリを作成していきます。
AWS のコンソールから『Elastic Container Registory』を選択します。
- パブリックを選択
- リポジトリ名を入力(今回は『blog』という名前にした)
下の画像のようにリポジトリが作成されていれば大丈夫です。
ここで作成した blog というレポジトリの中に自動的にイメージが保存されていきます。IAM ユーザーの作成
続いて、GitHubActions
から ECR
にイメージを push するための IAM ユーザーを作成します。
AWS のコンソールから『IAM』を選択して、ユーザーの追加を押します。
- 適当にユーザー名を入力
- 『アクセスキー - プログラムによるアクセス』を選択
- 『既存のポリシーを直接アタッチ』を選択
- AmazonEC2ContainerRegistryPowerUserを選択
以上を設定して、IAM ユーザーを作成します。ユーザーのリストに作成したユーザーが表示されていれば大丈夫です。
GitHubActions で使う、docker/login-action@v2のドキュメントに、『ECR に push するために、AmazonEC2ContainerRegistryPowerUser の権限がある IAM ユーザーを使え』と書いてあります。
https://github.com/marketplace/actions/docker-login
GitHubActions を使って ECR に push
参考: GitHubActions のドキュメント
https://docs.github.com/ja/actions
続きまして、GitHubActions による workflow を作成していきます。
内容としては
- job の発火タイミング: master ブランチへの push
- job の内容: docker イメージを作成して、ECR に push
これだけ。
これを /.github/workflows
ディレクトリ下に yaml ファイルとして記述していきます。
name: image-push-to-ECR
on:
push:
branches:
- main
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.SECRET_ACCESS_KEY }}
aws-region: ap-northeast-1
- name: Login to ecr
uses: docker/login-action@v2
with:
registry: ${{ secrets.ECR_ENDPOINT }}
- name: Build and push
id: docker-build
uses: docker/build-push-action@v2
with:
push: true
tags: ${{ secrets.ECR_ENDPOINT }}/${{ secrets.ECR_REPOSITORY }}:latest
cache-from: ${{ secrets.ECR_ENDPOINT }}/${{ secrets.ECR_REPOSITORY }}
- configure-aws-credentials
- AWS の認証情報を GitHubActions で便利に扱えるイメージ
- docker-login
- docker レジストリへのログインを GitHubActions でするためのイメージ
- buile-push-action
- docker イメージの push を GitHubActions でするためのイメージ
上記の 3 つの便利なイメージが公式から出ていたのでそれらのドキュメントを参考にしながら、ECR への push を実現しています
AppRunner でデプロイ
最後に、AppRunner でデプロイしていきましょう。
AWS のコンソールから『AWS App Runner』を選択します。
『サービスの作成』を選択
- 『コンテナレジストリ』を選択
- 『Amazon ECR』を選択
- コンテナイメージの URI を入力
- URI は ECR から確認できます。
- タグをつけるのも忘れずに
- 『自動』を選択
- 『新しいサービスロールの作成』を選択
- 『AppRunnerECRAccessRole』と入力
- 過去に作成したことがある人は、『既存のサービスロールを選択』から選択できます
- サービス名を適当に入力
- ポート番号を 3000 番に変更
ここまで設定できたら、サービスを作成します。
しばらくして、上の画像のようにステータスが『Running』になったら、指定された URL でブラウザからアクセスできるはず!!!
大成功!
最後に
以上が、Next.js
のアプリケーションを AppRunner
でデプロイする流れでした。
使った AWS のサービスは
- Elastic Container Registory
- App Runner
のみでそこまで複雑なことはしてないので、何か変な部分ではまらない限りは短時間でできるのではないでしょうか。ちなみに自分は、Docker
イメージを作成する部分でハマりまくって、動作するイメージを作成するまで 2 日間かかりました
こんなことをしておいてあれですが、ブログのホスティングにはできるだけお金をかけたくないので、一旦は Vercel
のホスティングで運用しようかなと思ってます
では
Bye