前言 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内容。实际上官方给的镜像文件就是这样的,这里正好分解学习一下为什么要这么写。