🦔

【Next.js】 Next.jsのDockerfileをコンテナサービス向けに書く

2022/10/05に公開

この記事の目的

この記事では個人開発でGCPのCloud Runなどのサービスに、コンテナ化したNext.jsをデプロイできるようにするためにDockerfileを書きます。
ローカルマシンでの開発ではyarn devを実行していればいいかなと思っているので特にこの記事でDocker化は検討しません。

実行環境

  • Docker: Docker version 20.10.17, build 100c701
  • yarn: 1.22.19
  • Next.js: 12.3.1
  • React: 18.2.0
  • OS: MacOS 12.3 (M1 Pro)

できたもの

FROM node:16.17.1-slim as builder
WORKDIR /app

COPY package.json yarn.lock ./
RUN yarn --prod --frozen-lockfile

COPY . .

RUN yarn build

FROM gcr.io/distroless/nodejs:16
ENV NODE_ENV production
WORKDIR /app

COPY --from=builder /app/public ./public
COPY --from=builder /app/.next ./.next
COPY --from=builder /app/node_modules ./node_modules

CMD ["./node_modules/.bin/next", "start"]

Dockerfile

自分の理解している範囲で上記のDockerfileについて解説します。

builder

FROM node:16.17.1-slim as builder

マルチステージビルドを行います。記事執筆時のLTSであるnode:16.17.1のslimイメージをベースイメージに利用します。ビルドするためのイメージになるので単にnodeやnode:alpineよりも影響を受けた記事により、node-slimを利用しています。

yarn install

COPY package.json yarn.lock ./
RUN yarn install --production --frozen-lockfile

今回はパッケージマネージャにyarnを利用しています。利用しているyarnのバージョンが1系のため、--frozen-lockfileを利用して依存するパッケージのバージョンの固定しています。

yarn build

COPY . .

RUN yarn build

ビルドします。

実行用

FROM gcr.io/distroless/nodejs:16
ENV NODE_ENV production
WORKDIR /app

nodejs向けのdistrolessイメージを利用しています。node16系を利用しているので、nodejs:16を利用します。お作法的にNODE_ENVWORKDIRを指定しています。

必要なものをbuilderからコピー

COPY --from=builder /app/public ./public
COPY --from=builder /app/.next ./.next
COPY --from=builder /app/node_modules ./node_modules

faviconなどが入っているpublic, ビルドの成果物が入っている.next, 起動用のコマンドが入ってるnode_modulesをbuilderからコピーします。

起動

CMD ["./node_modules/.bin/next", "start"]

用意した成果物を起動し、サーバに繋げたら無事成功です!
node_modules/.bin/nextnode_modules/next/dist/bin/nextのシンボリックリンクっぽいのでどちらを利用しても良さそうです。

その他雑記

  • rootユーザ以外でコマンドを実行することの検討
    • node-slimでCOPY --chown:node:node . .などを行うと、yarn build時にエラーが起きて自分では解決できなかったので今回はそこまではしないことにしました。
  • .dockerignoreファイルに追記したもの
    • ビルドに必要ないかなと思ったものを数点列挙するにとどめました。
.git
node_modules/
README.md
.gitignore
.next/
.swc/

最後に

間違いの指摘やより良い書き方のアドバイスなどあればぜひお願いします!
記事を読んでくださりありがとうございました。

参考にした記事

https://qiita.com/taquaki-satwo/items/f8fbe8b1efc4b2323ae7#1-dockerignore-で不要なファイルを除外
https://zenn.dev/jrsyo/articles/e42de409e62f5d
https://chore-update--yarnpkg.netlify.app/ja/docs/cli/install
https://blog.tagbangers.co.jp/ja/2022/08/22/nextjs-with-docker

Discussion