Docker 安装 Node.js

Node 镜像怎么选、生产镜像怎么写、node_modules 怎么处理。

Beginner
Key Points选 alpine 还是 slim 看原生依赖:alpine 用 musl,有些包要重新编译;生产用多阶段 + npm ci --omit=dev。

直接跑

Bash
docker run -it --rm -v "$PWD:/app" -w /app node:20-alpine sh
node -v
npm -v

生产 Dockerfile

Dockerfile
FROM node:20-alpine AS deps
WORKDIR /app
COPY package*.json ./
RUN npm ci

FROM node:20-alpine AS build
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build

FROM node:20-alpine AS runner
ENV NODE_ENV=production
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev && npm cache clean --force
COPY --from=build /app/dist ./dist
USER node
EXPOSE 3000
CMD ["node", "dist/server.js"]

镜像怎么选

TagSizeWhen
node:20~1.1GBDebugging, needs build tools
node:20-slim~200MBglibc native modules
node:20-alpine~130MBSmall, musl — some modules need rebuilding
node:20-alpine + distroless~110MBHardened production

node_modules 的三个坑

  • 宿主目录挂载会盖掉容器里的 node_modules → 加匿名卷 -v /app/node_modules
  • .dockerignore 不排除 node_modules,构建上下文会大到几百 MB
  • alpine 里 sharp、bcrypt 等原生模块要装 python3 make g++ 才能编译
Bash
# 开发时热更新
docker run -d --name dev -p 3000:3000 \
  -v "$PWD:/app" -v /app/node_modules \
  -w /app node:20-alpine npm run dev
Use npm ci, not npm install: the former installs exactly what package-lock.json says, so builds are reproducible.

Friends & Partners