开发环境下为何将npm依赖安装放在Docker的CMD命令中执行?
问题解答
1. CMD命令的运行逻辑
这个Dockerfile是专门面向开发环境设计的,整体运行逻辑如下:
- 镜像构建阶段仅执行3步:拉取node基础镜像、设置工作目录、复制
package.json和package-lock.json到镜像内,构建出来的镜像本身不包含node_modules依赖包 - 每次容器启动时才会顺序执行CMD里的三个命令:
- 先设置npm的缓存策略
- 执行
npm install安装依赖 - 启动开发模式的Node服务
- 配合Docker Compose的挂载配置:宿主机的
/tmp/history/npm-cache目录会被挂载到容器内npm默认的缓存目录/root/.npm,本地源码目录也会直接挂载到容器内的工作目录,实现代码修改热更新。
2. 和在RUN阶段执行npm install的核心区别
常规生产环境的Dockerfile都会把npm install放在RUN阶段,在镜像构建时就把依赖打包到镜像里,两种写法的差异主要针对开发场景的痛点优化:
- 放在RUN阶段的问题:
- 只要
package.json/package-lock.json有任何修改,对应Docker层就会失效,重新构建镜像时需要全量重新下载所有依赖,没有持久化的缓存可以复用 - 如果开发过程中需要新增/修改依赖,要么必须重新构建镜像,要么进入容器手动安装,手动安装的依赖在容器重启后就会丢失,非常影响开发效率
- 只要
- 放在CMD阶段的优势:
- npm的缓存文件持久化存在宿主机上,不管是否重新构建镜像、是否重建容器,只要缓存里有对应版本的依赖包,
npm install都不需要重新远程下载,安装速度极快 - 修改依赖后只需要重启容器就能完成依赖更新,不需要重新执行镜像构建流程
- npm的缓存文件持久化存在宿主机上,不管是否重新构建镜像、是否重建容器,只要缓存里有对应版本的依赖包,
3. 设置cache-min策略的原因
npm的cache-min参数用于配置npm优先使用本地缓存的时间阈值,单位为分钟:
- 当该参数设置为999999时,相当于告诉npm只要本地缓存里存在对应版本的依赖包,就直接复用,不需要主动向npm远程仓库查询是否有更新版本
- 这个配置可以跳过每次
npm install时的版本查询请求,进一步提升安装速度,同时开发环境依赖版本一般都会通过package-lock.json锁死,也不会出现版本不符合预期的问题。
内容的提问来源于stack exchange,提问作者Harrison Cramer
相关产品推荐
相关产品推荐

