前言 Next.js 除了在 vercel 上部署之外,更多的是部署在自己的服务器上,为此官方提供了 Docker 的打包运行方式。这里分享的是如何优化打包的 Docker 镜像大小。
新建默认项目 安装官方的命令建立项目。
1 npx create-next-app@latest
然后在项目根目录新建Dockerfile
文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 FROM node:20 WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . RUN npm run build EXPOSE 3000 CMD npm start
之后运行打包命令
1 docker image build -t image-size-initial .
然后会发现近 2GB 的大小。
第一步优化 使用较小的基础版本镜像 修改 node 版本,使用较小的基础版本镜像
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 FROM node:20 -aplineWORKDIR /app COPY package*.json ./ RUN npm ci COPY . . RUN npm run build EXPOSE 3000 CMD npm start
之后运行打包命令
1 docker image build -t image-size-apline .
发现少了一半的大小。
第二步 多阶段构建
也就每个阶段只构建需要的文件,而不是全部都包含在一起
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 FROM node:20 -apline AS depsWORKDIR /app COPY package*.json ./ RUN npm ci FROM node:20 -apline AS builderWORKDIR /app COPY --from=deps /app/node_modules ./node_modules COPY . . RUN npm run build FROM node:20 -apline AS runnerWORKDIR /app COPY --from=builder /app/next.config.mjs ./ COPY --from=builder /app/public ./public COPY --from=builder /app/node_modules ./node_modules COPY --from=builder /app/.next ./.next EXPOSE 3000 CMD ["node_modules/.bin/next" , "start" ]
之后运行打包命令,修改标签名
可观察到镜像少了 300MB 的样子。
第三步 Next.js 输出文件配置 修改 next.js.config.mjs 的内容,设置output
的值为standalone
。这里要注意的是官方提醒
We do not recommend using the runtimeConfig option, as this does not work with the standalone output mode. Instead, we recommend incrementally adopting the App Router. 我们不建议使用 runtimeProtect 选项,因为这不适用于独立输出模式。相反,我们建议逐步采用应用程序路由器。
1 2 3 4 5 6 const nextConfig = { output : "standalone" , }; export default nextConfig;
之后运行npm run build
命令,会在.next
文件夹中发现一个stanalone
文件夹,里面包含了所有的文件。
修改 Dockerfile 文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 FROM node:20 -apline AS depsWORKDIR /app COPY package*.json ./ RUN npm ci FROM node:20 -apline AS builderWORKDIR /app COPY --from=deps /app/node_modules ./node_modules COPY . . RUN npm run build FROM node:20 -apline AS runnerWORKDIR /app COPY --from=builder /app/.next/standalone ./ EXPOSE 3000 ENV PORT=3000 ENV HOSTNAME="0.0.0.0" CMD ["node" , "server.js" ]
之后打包可得镜像
看,现在只有135.56mb
内容。实际上官方给的镜像文件就是这样的,这里正好分解学习一下为什么要这么写。