結論
大体こんな感じになりました。
概要
WSL2 内に Next.js 環境を構築したので記録を付けます。
Docker も使えば Next.js サーバとデータベースのやり取りも容易に行えるので、それも目指します。
distrolessを使った本番環境と、yarn dev+ホットリロードができる開発環境の両方を準備します。
素の Next.js 環境の構築 (yarn)
- 公式サイトを参考に node.js 環境を準備します
https://nodejs.org/en/download/package-manager - 公式サイトを参考に yarn コマンドをインストールします
https://yarnpkg.com/getting-started/install - Next.js 環境構築用のコマンドを実行します
$ yarn create next-app --ts
開発環境 Docker イメージの作成
データベースも一緒にして docker compose 出来ると何かと便利なので、
先ほど構築した素の Next.js 環境と適当なデータベース(今回は MySQL)を一緒に使えるようにします。
先程構築した素の開発環境を volumes オプションでまるまる渡します(もっと良いやり方があるかも?)。
- Dockerfile.nextjs に開発環境イメージの構成を書きます
(次の docker-compose.yml で volumes 設定をするので、ここには VOLUME 設定を書かないでおきます)
FROM node:20
WORKDIR /app
RUN yarn install
CMD ["yarn", "dev"]
- docker-compose.yml を書きます
services:
nextjs:
build:
dockerfile: ./Dockerfile.nextjs
container_name: nextjs
volumes:
- ./:/app
ports:
- 3000:3000
database:
image: mysql:8.3.0
container_name: database
environment:
MYSQL_ROOT_PASSWORD: <いい感じのrootパスワード>
MYSQL_USER: <いい感じのユーザ名>
MYSQL_PASSWORD: <いい感じのパスワード>
MYSQL_DATABASE: <いい感じのデータベース名>
networks:
default:
name: nextjs-test-network
開発環境のホットリロード対応
素の Next.js 開発環境をそのまま Docker コンテナに入れると、ホットリロード機能(変更したファイルに対応するページが自動的に再読み込みされる機能)が動かないそうです。
以下のファイルに明示的に再読み込み設定を書くとよいらしいです。
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true, // ついでに Strict Mode を設定(必須ではないです)
webpack: (config) => { // ↓ここ以降を追加
config.watchOptions = { //
poll: 1000, //
aggregateTimeout: 300 //
} //
return config; //
} // ↑ここまで
};
export default nextConfig;
本番環境用の distroless イメージ環境
Next.js アプリを本番環境にデプロイする際におすすめの手法とのことです。
ただし、yarn コマンドどころか shell 環境すらないので、素の環境とは全く違った感覚でのセットアップが必要になります。
① Dockerfile.nextjs.prod を書きます
# 参考: https://zenn.dev/kazumax4395/articles/427cc791f6145b
# Build layer
# devDependenciesも含めてyarn installし、
# .next/ 内にNext.js関連の仕組みが動作するのに必要なファイルを出力
FROM node:20-slim as build
WORKDIR /app
COPY package.json yarn.lock ./
RUN yarn install --non-interactive --frozen-lockfile
COPY . .
#RUN yarn build:next && yarn build:server
# build:serverは必要ないらしい
RUN yarn build:next
# Package install layer
# dependencies をインストール、動作に必要なライブラリだけを取得する
FROM node:20-slim as node_modules
WORKDIR /app
COPY package.json yarn.lock ./
RUN yarn install --non-interactive --frozen-lockfile --prod
# Deploy layer
#
# イメージサイズやセキュリティの視点からおすすめのイメージとのこと
FROM gcr.io/distroless/nodejs20-debian12
WORKDIR /app
ENV NODE_ENV production
COPY package.json yarn.lock next.config.mjs ./
COPY --from=build /app/public ./public
COPY --from=build /app/.next ./.next
# ここでも server/index.ts 関連の指定はいらないらしい
# package.json の start で指定しているからそれで十分なのだろうか
#COPY --from=build /app/dist ./dist
COPY --from=node_modules /app/node_modules ./node_modules
CMD ["node_modules/.bin/next", "start"]
② docker-compose-prod.yml を書きます、ほとんど docker-compose.yml ファイルと同じです
services:
nextjs:
build:
dockerfile: ./Dockerfile.nextjs.prod #ここだけ本番環境用に変更
container_name: nextjs
ports:
- 3000:3000
database:
image: mysql:8.3.0
container_name: database
environment:
MYSQL_ROOT_PASSWORD: <いい感じのrootパスワード>
MYSQL_USER: <いい感じのユーザ名>
MYSQL_PASSWORD: <いい感じのパスワード>
MYSQL_DATABASE: <いい感じのデータベース名>
networks:
default:
name: nextjs-test-network
終わりに
NGINX + React 環境で開発してきたので、特にホットリロードをはじめとする Next.js 環境の便利さには目を見張るものがあります!
Next.js の開発環境や、本番環境(ビルド結果)が動作するのにどのファイルが必要で、
どのように配置する必要があるのか、どのように実行する必要があるのか...
完全に把握できるまで、もう少し設定の確認や記事の修正を行おうと思います。
参考記事