如何使用Docker构建Next.js的生产环境和开发环境
动机
我在开发环境和生产环境中尝试使用Docker时遇到了一些困难,所以我将记录下使用Docker构建Next.js环境的方法作为备忘录。
开发环境
根据公式模板进行制作。
FROM node:18-alpine
WORKDIR /app
COPY package.json yarn.lock* ./
RUN if [ -f yarn.lock ]; then yarn --frozen-lockfile; \
else echo "Warning: Lockfile not found. It is recommended to commit lockfiles to version control." && yarn install; \
fi
COPY src ./src
COPY public ./public
COPY next.config.js .
COPY tsconfig.json .
CMD ["yarn", "dev"]
1行目:我們在v18的節點上進行建立。
3行目:指定工作目錄。
5行目:將package.json和yarn.lock複製到容器內。如果使用npm,將yarn.lock改為package-lock.json或其他。
6行目:安裝所需的套件。如果使用npm,將npm ci替換為npm ci。也可以在官方模板中使用條件判斷。
10至13行目:將啟動所需的代碼複製到容器內。
15行目:使用yarn dev啟動伺服器。如果使用npm,將npm run dev替換為npm run dev。
接下来我们来创建docker-compose。
请将以下内容写入docker-compose.dev.yml。
services:
app:
build:
context: .
dockerfile: Dockerfile.dev
image: next-app
container_name: next-app
ports:
- '3001:3001'
env_file:
- .env
volumes:
- ./src:/app/src
- ./public:/app/public
- node_modules:/app/node_modules
restart: always
tty: true
stdin_open: true
volumes:
node_modules:
通过以下命令可以启动容器。
docker compose -f docker-compose.dev.yml build
docker compose -f docker-compose.dev.yml up -d
正式环境
由于使用了Next公式的模板无法正常工作,我们将根据由docker init创建的Dockerfile和docker-compose进行构建。由于下面的文件是针对yarn的,所以如果要使用npm,请相应地将yarn run build或yarn start的部分改写为适用于npm的形式。
# syntax=docker/dockerfile:1
# Comments are provided throughout this file to help you get started.
# If you need more help, visit the Dockerfile reference guide at
# https://docs.docker.com/engine/reference/builder/
ARG NODE_VERSION=18.16.0
################################################################################
# Use node image for base image for all stages.
FROM node:${NODE_VERSION}-alpine as base
# Set working directory for all build stages.
WORKDIR /usr/src/app
################################################################################
# Create a stage for installing production dependecies.
FROM base as deps
# Download dependencies as a separate step to take advantage of Docker's caching.
# Leverage a cache mount to /root/.yarn to speed up subsequent builds.
# Leverage bind mounts to package.json and yarn.lock to avoid having to copy them
# into this layer.
RUN --mount=type=bind,source=package.json,target=package.json \
--mount=type=bind,source=yarn.lock,target=yarn.lock \
--mount=type=cache,target=/root/.yarn \
yarn install --production --frozen-lockfile
################################################################################
# Create a stage for building the application.
FROM deps as build
# Copy the rest of the source files into the image.
COPY . .
# Run the build script.
RUN yarn run build
################################################################################
# Create a new stage to run the application with minimal runtime dependencies
# where the necessary files are copied from the build stage.
FROM base as final
# Use production node environment by default.
ENV NODE_ENV production
# Run the application as a non-root user.
USER node
# Copy package.json so that package manager commands can be used.
COPY package.json .
# Copy the production dependencies from the deps stage and also
# the built application from the build stage into the image.
COPY --from=deps /usr/src/app/node_modules ./node_modules
COPY --from=build /usr/src/app/.next ./.next
COPY ./public ./public
# Run the application.
CMD yarn start
version: '3'
services:
next-app:
container_name: next-app-prod
image: next-app-prod
build:
context: .
dockerfile: Dockerfile.prod
args:
ENV_VARIABLE: ${ENV_VARIABLE}
NEXT_PUBLIC_ENV_VARIABLE: ${NEXT_PUBLIC_ENV_VARIABLE}
restart: always
ports:
- 4400:4400
在中国,您可以使用以下命令启动容器。当您更新应用程序时,也可以使用类似的命令进行更新。
参考链接:https://matsuand.github.io/docs.docker.jp.onthefly/compose/production/
docker compose -f docker-compose.prod.yml build
docker compose -f docker-compose.prod.yml up -d
结束
本次记录了使用Docker构建生产环境和开发环境的方法。下一次我们将使后端也能够在Docker中创建,并实现后端与客户端之间的通信。
以下是可供參考的資料。
Next.js官方代码库
https://github.com/vercel/next.js/tree/canary/examples/with-docker-compose/next-app
Docker 手册
https://matsuand.github.io/docs.docker.jp.onthefly/compose/production/
追加记录
2023年9月27日,修复了在正式环境中无法传送public目录内文件的问题。