【Next.js】 Next.jsのDockerfileをコンテナサービス向けに書く
この記事の目的
この記事では個人開発で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 /app/public ./public
COPY /app/.next ./.next
COPY /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_ENV
とWORKDIR
を指定しています。
必要なものをbuilderからコピー
COPY /app/public ./public
COPY /app/.next ./.next
COPY /app/node_modules ./node_modules
faviconなどが入っているpublic
, ビルドの成果物が入っている.next
, 起動用のコマンドが入ってるnode_modules
をbuilderからコピーします。
起動
CMD ["./node_modules/.bin/next", "start"]
用意した成果物を起動し、サーバに繋げたら無事成功です!
node_modules/.bin/next
はnode_modules/next/dist/bin/next
のシンボリックリンクっぽいのでどちらを利用しても良さそうです。
その他雑記
- rootユーザ以外でコマンドを実行することの検討
- node-slimで
COPY --chown:node:node . .
などを行うと、yarn build
時にエラーが起きて自分では解決できなかったので今回はそこまではしないことにしました。
- node-slimで
- .dockerignoreファイルに追記したもの
- ビルドに必要ないかなと思ったものを数点列挙するにとどめました。
.git
node_modules/
README.md
.gitignore
.next/
.swc/
最後に
間違いの指摘やより良い書き方のアドバイスなどあればぜひお願いします!
記事を読んでくださりありがとうございました。
参考にした記事
Discussion