Next.js + Docker 部署最佳实践
本文总阅读量次
最近在处理 Next.js 项目的发布流程,实际场景是在本地完成开发后,将代码同步到 Linux 服务器并构建 Docker 镜像。中间踩了一些配置上的坑,也优化了一下构建流程,顺手记录一下这套最佳实践清单。

1. 代码增量同步
在本地开发完成后,我习惯用 rsync 将代码增量同步至服务器。只要配置好 SSH 免密登录,一行命令就能搞定发布:
# --dry-run: 也就是“演习”模式,拿不准 excludes 规则时可以先加上这个参数看看会删哪些文件
# 注意:源路径 /mnt/d/... 需根据本地使用的 Shell 环境(如 Git Bash 或 WSL 挂载路径)进行调整
rsync -avP \
--delete \
--exclude-from='rsync.ignore' \
/mnt/d/Project/* xxxx@xxxx:~/data/
这里有个细节需要注意:在 rsync.ignore 里排除文件夹时,务必带上后缀 /。 比如想排除本地的构建缓存和依赖,要写 .next/ 和 node_modules/,避免将本地环境的产物同步到服务器,导致环境不兼容。
2. Next.js 项目配置避坑
为了配合服务器端的 Docker 部署,next.config.js 里有几个关键点需要调整。
首先是 Standalone 模式。这是后续 Docker 镜像“瘦身”的前置关键步骤。开启此选项后,Next.js 会自动分析依赖关系,只打包生产环境实际运行所需的必要文件:
module.exports = {
output: 'standalone',
// ... 其他配置
}
另外遇到过两个小问题:
- UUID 兼容性:原生
crypto.randomUUIDAPI 受浏览器安全策略限制,如果项目部署后是通过 IP 地址(而非 HTTPS 或 localhost)访问,浏览器会报错,导致依赖该方法的组件交互直接失效。建议直接引入第三方uuid库来替代,兼容性更稳妥。 - pnpm postinstall:如果使用了
pnpm install --ignore-scripts,package.json里的postinstall钩子虽然当下不执行,但别担心,下次运行pnpm build时 PNPM 会自动把这些漏掉的脚本补回来。
3. 生产级 Dockerfile 模板
最后贴一下优化后的 Dockerfile。这是一个多阶段构建脚本,基于 node:22-slim。
这个配置主要包含三个核心亮点:
- 构建加速:利用 BuildKit 的挂载缓存特性(
--mount=type=cache),复用 pnpm store,大幅提升服务器端的反复构建速度。 - 多阶段构建:清晰分离环境预设、依赖安装、构建打包和最终运行环境。
- 极简体积:配合前文开启的 Standalone 模式,在最终阶段只拷贝
.next/standalone及必要的静态资源。这使得最终镜像体积大幅减小,不再包含开发依赖和冗余文件。
# ==========================================
# Stage 1: Base (环境预设)
# ==========================================
FROM node:22-slim AS base
ENV NEXT_TELEMETRY_DISABLED 1
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
# 启用 corepack 以支持 pnpm
RUN corepack enable
WORKDIR /app
# ==========================================
# Stage 2: Deps (依赖安装)
# ==========================================
FROM base AS deps
COPY package.json pnpm-lock.yaml ./
# 挂载 pnpm store 缓存,加速后续构建
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile --ignore-scripts
# ==========================================
# Stage 3: Builder (项目构建)
# ==========================================
FROM base AS builder
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN pnpm build
# ==========================================
# Stage 4: Runner (生产运行)
# ==========================================
FROM base AS runner
ENV NODE_ENV production
ENV PORT 3000
# 安全起见,新建用户运行,不要用 root
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
# 只拷贝 Standalone 及其依赖资源,体积大幅减小
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
CMD ["node", "server.js"]
在服务器构建时,通常建议不使用缓存强制拉取最新层(视情况而定),或者使用 docker build --pull=false . 利用本地缓存加速。这套流程目前跑下来比较顺滑,既保证了发布效率,也兼顾了线上镜像的体积和安全性。