0
1
Login
docs: 教程文档
README

利用缓存提升构建速度

介绍

众所周知,缓存是性能优化一个重要手段。在 CI 领域,利用好缓存能极大提升流水线构建速度!

下面以前端 NodeJS 为例,介绍两种有效的利用缓存提升构建速度的方法。

no cache

我们先准备一份 package.json ,里面有这些模块:

{
  "dependencies": {
    "angular": "^1.8.3",
    "eslint": "^9.15.0",
    "jest": "^29.7.0",
    "koa": "^2.15.3",
    "next": "^15.0.3",
    "nuxt": "^3.14.159",
    "react": "^18.3.1",
    "vue": "^3.5.13",
    "webpack": "^5.96.1"
  }
}

在流水线上执行 npm install,流水线配置文件:

main:
  push:
    "no-cache":
      docker:
        image: node:22-alpine
      stages:
        - name: npm install
          script: npm install

执行效果:

no-cache

由于没有 cache,会从网络下载资源,耗时约 23s。

volume cache

云原生构建 利用 Docker 的 volumes 功能,可在配置文件中通过声明 pipeline.docker.volumes, 将构建机上目录 mount 到容器中。构建任务可将下载好的依赖放入构建机缓存,供后续流水线使用。

Node 流水线配置文件:

main:
  push:
    "volume-cache":
      docker:
        image: node:22-alpine
        volumes:
          - node_modules:copy-on-write
      stages:
        - name: npm install
          script: npm install

多执行几次,命中缓存后执行效果:

fit volume cache

可以看到前面截图中 added 1973 packages from 1072 contributors 字样消失了,增加了 up to date 字样,无需从网络下载资源,耗时降为 13s。

volumes 的缺点是,缓存只在当前构建机有效。云原生构建 会根据项目构建并发情况,动态在几台构建机上分配一台作为当前流水线构建机,后续流水线分配了其他无缓存的构建机,仍会重新从网络下载资源。

Maven 流水线配置文件:

main:
  push:
    - docker:
        # 可以去 dockerhub 上 https://hub.docker.com/_/maven 找到您需要 maven 和 jdk 版本
        image: maven:3.8.6-openjdk-8
        volumes:
          - /root/.m2:cow
      stages:
        - name: build
          script: mvn clean package

Gradle 流水线配置文件:

master:
  push:
    - docker:
        # 可以去 dockerhub 上 https://hub.docker.com/_/gradle 找到您需要 gradle 和 jdk 版本
        image: gradle:6.8-jdk8
        volumes:
          - /root/.gradle:copy-on-write
      stages:
        - name: build
          script: ./gradlew bootJar

docker cache

云原生构建 还提供了一种 cache 方式:在一个镜像中 npm install 好依赖,然后缓存这个镜像在当前构建机,并推送到远端镜像源。

后续流水线使用时,若构建机有镜像缓存,则直接使用。若构建机无镜像缓存,则会从远端镜像源拉取下来。

docker:cache 内置任务使用示例:

master:
  push:
    - stages:
        - name: build cache image
          type: docker:cache
          options:
            dockerfile: cache.dockerfile
            by:
              - package.json
              - package-lock.json
            versionBy:
              - package-lock.json
          exports:
            name: DOCKER_CACHE_IMAGE_NAME
        - name: use cache
          image: $DOCKER_CACHE_IMAGE_NAME
          commands:
            - cp -r "$NODE_PATH" ./node_modules

cache.dockerfile 示例:

# 选择一个 Base 镜像
FROM node:16

# 设置工作目录
WORKDIR /space

# 将 by 中的文件列表 COPY 过来
COPY . .

# 根据 COPY 过来的文件进行依赖的安装
RUN npm ci

# 设置好需要的环境变量
ENV NODE_PATH=/space/node_modules

无镜像,需要构建并推送镜像的效果:

build cache

可以看到耗时同直接 npm install 接近,约 31.5s。

后续构建,构建机无镜像,需要 pull 的效果,待补充

后续构建,若构建机有镜像,直接使用的效果:

local cache

耗时降到 2.7s,效果非常明显!

对比

缓存

  • volumes:缓存在构建机,效果好
  • docker:cache:缓存在构建机和远端,效果好

复杂度

  • volumes:配置简单,清晰易懂
  • docker:cache:配置复杂,涉及配置文件、dockerfile,有一定理解、使用成本

跨流水线

  • volumes:同一个构建机中,可跨流水线共享缓存,不可跨构建机
  • docker:cache:流水线执行过程中,流水线独享。缓存镜像构建完成、推送到远端后,可跨流水线、跨构建机使用

缓存更新

  • volumes:可控制读写权限,适用更多场景
  • docker:cache:重新构建缓存镜像并推送到远端,其他构建机需重新拉取。

完整示例

参见 .cnb.yml

具体效果对比,可于本仓库的云原生构建列表页查看流水线,或 fork 后自行尝试。

About

利用缓存提升构建速度

贡献者
1

Language
Markdown83.9%
Dockerfile15.7%
gitignore0.4%