Docker多阶段构建中清理npm缓存与node_modules是否必要?
我正在学习Docker,最初使用的Dockerfile如下:
FROM node WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . RUN npm run build && npm cache clean --force && rm -rf node_modules CMD ['npm', 'start']
了解多阶段构建后,我将Dockerfile修改为:
FROM node AS builder WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . RUN npm run build FROM node:lts-alpine WORKDIR /app COPY --from=builder /dist /app CMD ['npm', 'start']
我本以为可以移除npm cache clean --force && rm -rf node_modules,因为这些产物不会出现在最终镜像中,还能加快构建速度。但看到资料称这些产物仍会留在缓存中占用空间。
于是我做了测试:
- 执行
docker builder prune --all; - 保留清理命令构建镜像;
- 再次执行
docker builder prune --all,清理后总占用912.7MB; - 移除清理命令构建镜像;
- 再次执行
docker builder prune --all,清理后总占用仍为912.7MB。
构建后执行docker history <image>也未发现差异。请问:
- npm缓存和node_modules是否真的会被Docker缓存占用空间?
- 我能否使用无清理命令的Dockerfile以提升速度?
- 保留清理命令是否属于最佳实践?
1. npm缓存和node_modules是否会占用Docker构建缓存空间?
是的,但你的测试结果无差异,是因为docker builder prune --all会彻底清理所有未被使用的构建缓存(包括builder阶段产生的中间层)。在多阶段构建中,builder阶段的node_modules和npm缓存确实会作为中间层保存在构建缓存里,但只要你不保留builder阶段的镜像,且定期清理缓存,这些临时产物不会长期占用空间。
需要注意:如果构建频繁重复,且builder阶段的层没有变动(比如package*.json没修改),Docker会复用这些缓存层,此时node_modules和npm缓存会一直存在于缓存中,直到你手动清理或者缓存被新的构建覆盖。
2. 能否使用无清理命令的Dockerfile提升构建速度?
完全可以。移除清理命令后,builder阶段的node_modules和npm缓存会被保留在构建缓存中,当后续构建时如果package*.json没有变化,Docker会直接复用RUN npm ci的缓存层,跳过重新安装依赖的步骤,大幅提升构建速度。
而且由于多阶段构建的最终镜像只复制/dist目录,这些缓存产物根本不会进入最终镜像,完全不影响最终镜像的大小。
3. 保留清理命令是否属于最佳实践?
在多阶段构建的builder阶段,保留清理命令已经不是最佳实践,原因如下:
- 增加构建时间:每次构建都要执行
npm cache clean和rm -rf node_modules,反而拖慢构建速度; - 导致缓存失效:清理命令会让
RUN npm run build && ...这一层无法被复用,即使代码没有变动,也需要重新构建; - 无实际收益:这些产物不会进入最终镜像,只要定期清理构建缓存(比如用
docker builder prune),就不会造成空间浪费。
唯一的例外场景是:如果你的构建环境磁盘空间极其紧张,且无法定期执行缓存清理,此时在builder阶段清理临时产物可以减少缓存占用的瞬时空间,但这种情况非常少见。
内容的提问来源于stack exchange,提问作者Noberto Pessoa

