如何保存Docker多阶段构建生成的中间镜像?Travis缓存场景
当然可以缓存多阶段构建中的
deps镜像! 完全没问题,这正是针对多阶段构建优化Travis CI构建速度的绝佳方案——毕竟你的deps阶段包含了大量耗时的依赖安装操作,缓存它能省不少时间。下面是具体的实现步骤:
核心思路
利用docker save将构建好的deps阶段镜像导出为本地tar包,存入Travis的缓存目录;下次构建时先用docker load恢复这个镜像,Docker会自动复用镜像中的所有已构建层,跳过重复的npm安装等操作。
具体配置步骤
1. 调整Travis配置文件(.travis.yml)
首先要在Travis配置里指定缓存目录,然后添加构建前后的脚本逻辑:
cache: directories: - $HOME/docker_cache # 用来存放缓存的Docker镜像tar包 before_script: # 确保缓存目录存在 - mkdir -p $HOME/docker_cache # 如果缓存的deps镜像存在,就加载它 - if [ -f $HOME/docker_cache/deps.tar ]; then docker load < $HOME/docker_cache/deps.tar; fi script: # 先构建deps阶段并打上标签(如果镜像已加载,Docker会直接复用层) - docker build --target deps -t my-app-deps . # 将deps镜像保存到缓存目录 - docker save my-app-deps > $HOME/docker_cache/deps.tar # 继续构建完整的最终镜像 - docker build -t my-app-final .
2. (可选)优化缓存失效逻辑
如果你的package.json或package-lock.json更新了,需要重新构建deps镜像。可以通过给镜像标签添加依赖文件的哈希值来实现自动失效:
script: # 计算package-lock.json的哈希值,作为镜像标签的一部分 - DEPS_TAG=$(md5sum client/package-lock.json | cut -d' ' -f1) - docker build --target deps -t my-app-deps:$DEPS_TAG . - docker save my-app-deps:$DEPS_TAG > $HOME/docker_cache/deps-$DEPS_TAG.tar # 构建最终镜像时指定使用缓存的deps镜像 - docker build --build-arg DEPS_IMAGE=my-app-deps:$DEPS_TAG -t my-app-final .
对应的Dockerfile可以调整为:
ARG DEPS_IMAGE=danlynn/ember-cli:3.0.0 FROM $DEPS_IMAGE AS deps RUN mkdir -p /client COPY client/package.json /client/ COPY client/package-lock.json /client/ WORKDIR /client RUN npm install node-sass RUN npm install RUN npm rebuild node-sass # ... 其他耗时操作 FROM node:wheezy AS server COPY --from=deps /client/ /client/
这样只有当依赖文件变化时,才会重新构建并缓存新的deps镜像,否则一直复用之前的缓存。
注意事项
- 确保Travis CI的Docker环境支持多阶段构建(Docker版本≥17.05,Travis默认环境一般满足);
- 缓存的tar包可能会比较大,Travis对缓存大小有一定限制,如果体积过大,可以考虑清理镜像中的无用文件后再保存;
- 如果你在
deps阶段有后续的动态修改,需要确保这些修改也被包含在保存的镜像中(不过你的Dockerfile里都是静态的依赖安装,没问题)。
内容的提问来源于stack exchange,提问作者Skarab
相关产品推荐
相关产品推荐

