加 3 行代码减少 80% 构建时间

Dockerfile命令详解之 RUN(三):RUN --mount=type=cache 在官方文档中,对RUN --mount=type=cache类型挂载的释义是 "挂载一个临时目录来缓存编译器和包管理器的目录" 。但这里不一定只是编译器或者包管理器,可以是任意的缓存目录。 阅读详情

作者:Whilconn

https://juejin.cn/post/7135756687134162980

背景

最近接手的BI项目在Jenkins的构建机上构建耗时比较久,日常构建耗时都在 20min 以上,即使改动一行代码也要构建这么久。构建耗时截图如下:

 

构建耗时较长导致日常测试和正式发版都会浪费很多时间等待,对研发流程影响较大(主要是我忍不了)。因此需要对构建速度进行优化。

优化思路分析

要优化项目的构建速度,得先了解构建流程:

  • 开发人员推送代码到 Gitlab,触发 Gitlab 服务器的 Push Events

  • Push Events被触发后,会调用提前配置好的 Jenkins webhooks

  • Jenkins webhooks被调用后,会执行对应项目的构建任务

  • 构建任务开始后先拉取项目源码到构建机,再使用docker build构建镜像

  • docker 构建镜像分为两个阶段,先使用npm scripts构建前端项目,然后把构建产物拷贝到nginx基础镜像

在这个流程中,可以优化的环节只有构建docker镜像这一步,其他环节的耗时基本可以忽略不计。而在不大改项目的情况下能起到明显提速效果的方案是:缓存策略。构建docker镜像时可以用到的缓存包括两类:docker层缓存和应用层缓存。

docker层缓存是指docker build所产生的可重用镜像层,只要Dockerfile中的命令及相关的源文件未改变,就能直接使用这些镜像缓存。这种缓存策略在代码不改变的情况下效果很好,构建耗时甚至可以控制在 10 秒内。而对于日常开发情况下,代码频繁变化,如果应用本身构建时间又很长,则需要使用应用层缓存。(上一篇文章《docker build 缓存失效分析》中有 docker 层缓存相关介绍,也可以看看官方文档[1]、中文文档[2],本文不再赘述)

应用层缓存是指应用构建所产生的中间产物,这些中间产物主要是node_modules目录中的物理文件,其中包括npm install下载的依赖包和npm run build产生的.cache目录文件。而docker build每次都会初始化全新的环境用于构建,新环境中不存在node_modules目录,因此每次都是重新写入而无法复用,得想办法复用该目录下的文件;另外npm run build需要开启缓存功能,才会输出缓存文件到node_modules/.cache目录。

综上,优化思路主要是两点:1、开启应用层构建缓存(如webpack cache);2、持久化node_modules目录,确保每次npm install和npm run build都能复用该目录下的文件。

开启应用层构建缓存

项目使用的技术是React,构建主要依靠react-scripts@4.0.3,底层实际调用的是webpack@4.44.2,应用构建缓存主要来自webpack。webpack需要手工开启缓存功能(官方文档传送门[3]),配置cache属性为true即可。

实际操作只有 1 步, 找到webpack.config.js设置cache:true,代码如下:

module.exports = {
  //...
  cache: true
};

本地首次npm run build构建,无缓存的情况下,耗时 13min 左右。

启用缓存后在本地进行二次构建,有缓存的情况下,无论是否修改源码构建耗时均为 4min 左右,比优化前的 13min 有明显提升。 构建耗时截图如下:

实际上,webpack@4的缓存只在watch和development模式下生效,在上述构建测试中其实不起作用。 实测删除wepack中的cache:true配置,或者配置为cache:false,二次构建时间也是 4min 左右。

之所以构建速度提升了那么多,是因为react-scripts的webpack配置中开启了babel-loader和eslint-webpack-plugin的缓存功能,另外terser-webpack-plugin配置也默认开启了缓存功能。从缓存目录node_modules/.cache中也能看到它们的缓存文件。

所以,这一步其实啥也不用做,如果想进一步提速可以升级到webpack@5。

持久化node_modules目录

想在docker build环境中持久化node_modules需要使用到BuildKit的mount功能,该功能有几个前置条件:

  • docker 版本必须高于 18.09

  • BuildKit需要手工启用,可在docker build命令前添加环境变量DOCKER_BUILDKIT=1启用

  • 如果前两个条件不满足,则需要具备Jenkins和构建机的读写权限,以调整构建环境参数

  • 修改Dockerfile,使用RUN --mount=type=cache运行npm install和npm run build指令(--mount=type=cache说明文档传送门[4])

开启BuildKit还有其他特性[5],比如输出日志更友好,基本每一步都会输出耗时,就这一条,值了!

实际操作分为 2 步:
1、修改Jenkins配置,在docker build命令前加上环境变量。修改后镜像构建命令长这样:

 DOCKER_BUILDKIT=1 docker build .

2、修改Dockerfile,将RUN npm install和RUN npm run build指令改为RUN \--mount=type=cache npm xxx。修改后Dockerfile长这样:

FROM node:alpine as builder

WORKDIR /app

COPY package.json /app/

RUN --mount=type=cache,target=/app/node_modules,id=my_app_npm_module,sharing=locked \
    --mount=type=cache,target=/root/.npm,id=npm_cache \
    npm i --registry=https://registry.npm.taobao.org

COPY src /app/src

RUN --mount=type=cache,target=/app/node_modules,id=my_app_npm_module,sharing=locked \
    npm run build

文档说由于 BuildKit 为实验特性,需要在 Dockerfile 文件开头加上如下代码:# syntax = docker/dockerfile:experimental。在Docker 20.10环境下,加了上述代码反而构建报错,原因是加载外网资源失败,删除后构建成功。这不就是玄学吗?🤡

优化结果

在配置好缓存策略后,模拟日常开发修改项目代码触发自动构建流程,构建耗时从 20min+下降到 4min+,总体耗时减少 80%。整个优化过程修改了Jenkins的一行配置,另外在Dockerfile中添加了3行代码,改动很少但效果很不错。

 

参考资料

[1]

官方文档: https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#leverage-build-cache

[2]

中文文档: https://vuepress.mirror.docker-practice.com/appendix/best_practices/#%E6%9E%84%E5%BB%BA%E7%BC%93%E5%AD%98

[3]

传送门: https://v4.webpack.js.org/configuration/other-options/#cache

[4]

传送门: https://vuepress.mirror.docker-practice.com/buildx/buildkit/#run-mount-type-cache

[5]

其他特性: https://docs.docker.com/develop/develop-images/build_enhancements/#new-docker-build-command-line-build-output

Docker笔记-08 Docker BuildKit Docker Buildx 是一个docker CLI插件,其扩展了docker命令,支持Moby BuildKit提供的功能。 阅读详情

相关推荐

2.6 Docker镜像优化技巧:多阶段构建让你的镜像体积减少80%

Docker镜像优化技巧摘要 通过多阶段构建、精简基础镜像和清理缓存等技术,可将Docker镜像体积减少80%以上。多阶段构建分离构建环境和运行时环境,仅复制必要文件;使用Alpine或Distroless基础镜像替代标准镜像;合并RUN指令减少层数;合理编排COPY顺序利用缓存;添加.dockerignore排除非必要文件。实战案例显示,Node.js应用镜像从900MB优化至150MB(减少83%),Go应用从800MB降至15MB(减少98%)。配合dive等分析工具,可系统性地优化镜像大小,提升部署

yonggeit的博客 3444

使用 `--mount=type=cache` 提升 Docker 构建效率:原理解析与工程实战指南

随着容器化系统构建规模的扩大和 CI/CD 并发构建频率的提升,传统 Dockerfile 中基于指令缓存的方式难以满足缓存粒度控制与构建性能优化的需求。BuildKit 提供的 `--mount=type=cache` 功能,突破了以层为单位的构建缓存边界,允许用户在运行时挂载可复用缓存路径,实现如依赖下载、编译缓存等中间态数据的高效持久化管理。本文将基于真实项目实践,从缓存挂载的底层机制出发,系统讲解 `type=cache` 的语法结构、生命周期、最佳使用场景以及企业级构建流程中的性能收益。配套完整用

努力分享一些人工智能、计算机视觉、影像等相关的知识干货! 1385

LangGraph实战:如何用循环机制优化你的LangChain Agent工作流

本文详细介绍了如何使用LangGraph的循环机制优化LangChain Agent工作流,解决传统AgentExecutor在强制工具调用、动态提示调整和多阶段循环中的局限性。通过状态机和显式状态图设计,LangGraph提供了更精准的流程控制能力,适用于复杂AI应用场景。

weixin_30316097的博客 486

你不知道的Docker缓存陷阱:--mount=type=cache正确姿势大公开

掌握Docker镜像的多阶段构建缓存优化(--mount=cache)技巧,有效提升构建效率。适用于CI/CD、微服务部署等高频构建场景,通过合理挂载缓存层减少重复下载与编译。显著加速构建过程、降低资源消耗,值得收藏。

AlgoChat的博客 838

python爬虫入门教程(非常详细)

爬虫指的是一种自动化程序,能够模拟人类在互联网上的浏览行为,自动从互联网上抓取、预处理并保存所需要的信息。爬虫运行的过程一般是先制定规则(如指定要抓取的网址、要抓取的信息的类型等),紧接着获取该网址的HTML源代码,根据规则对源代码进行解析和抽取,最后进行处理和保存。爬虫在实际应用中广泛使用,如搜索引擎、大数据分析、交易数据采集等领域,都需要用到爬虫技术来实现信息的定向采集和处理。

工宗浩生财指南针 2万+

abaqus 根据坐标施加载荷- Analytical Field 载荷映射

在一些类型的分析中,需要将按位置分布的载荷施加到结构上,比如流体分析导出了结构的气动载荷、或者温度载荷,需要将压强分布、温度分布载荷施加到固体上。这种分析可以使用abaqus中的Analytical Field实现。 1 例子 1.1 结构 一个100*100mm的面,面的载荷分布函数为p=(x2+y2)0.5/((20.5)*100) MPa,即(0, 0)的压强为0,(100, 100)的压强为1。 1.2 载荷 载荷函数:p=(x^2+y^2)^0.5/((2^0.5)*100) in exce.

shengyutou的博客 2万+

docker buildkit 缓存.m2 加速构建

MAVEN_BUILD --mount=type=cache DOCKER_BUILDKIT=1 临时使用buildkit方式构建。(不须要修改docker配置文件)

lswzw的博客 2257

宝骏kiwi 630 730 560 E100 E200 E300 310 510 610 330 530维修手册电路图资料线路图接线图更新

2020-2022年宝骏RS-3维修手册和电路图。2020-2022年宝骏RS-3维修手册和电路图。2019-2021年宝骏RC-6维修手册和电路图。2019-2021年宝骏RC-6维修手册和电路图。2019-2020年宝骏RS-5维修手册和电路图。2019-2020年宝骏RS-5维修手册和电路图。2019-2020年宝骏RM-5维修手册和电路图。2019-2020年宝骏RM-5维修手册和电路图。2019-2021年宝骏510维修手册和电路图。2019-2021年宝骏510维修手册和电路图。

weixin_45821055的博客 1771

构建时间减少80%,多阶段Docker缓存优化的黄金法则揭秘

掌握Docker镜像的多阶段构建缓存优化,显著提升CI/CD效率。通过分层缓存、依赖前置与阶段复用,减少重复构建,适用于微服务与持续集成场景,构建时间最高降低80%。方法实用高效,值得收藏。

AlgoInk的博客 989

并网逆变器学习笔记5---三电平DPWM

三电平DPWM

圆桌骑士的博客 1万+

kettle从入门到精通 第九十二课 ETL之kettle 使用Kettle的Carte对外发布读写接口

场景:使用kettle实现将查询结果返回给客户端,也就是说kettle暴露查询接口供外围系统调用。前提必须是使用carte服务才可以提供接口供外部系统调用。具体实操方法如下:1、设计转换根据具体需求设计转换,主要用到的步骤有获取变量(从请求参数中获取变量)、json输入(解析入参),json 输出将结果转换为json格式输出到客户端。如下图所示:2、接收参数使用获取变量步骤来接收接口请求参数,变量通过${}方法进行获取,如下图${PARAM}则是获取PARAM参数,将参数赋值为req字段。

zhangjin1222的博客 954

Flutter-Action 缓存优化技巧:如何减少 CI/CD 构建时间 80%

Flutter-Action 是一款专为 GitHub Actions 打造的 Flutter 环境配置工具,支持 Linux、Windows 和 macOS 系统。在 CI/CD 流程中,合理配置缓存策略可以显著提升构建效率,本文将分享 3 个实用的缓存优化技巧,帮助你减少 80% 的构建时间。 ## 一、核心缓存路径配置 Flutter 构建过程中会产生大量依赖文件,通过缓存这些文件可以避

gitblog_00365的博客 1085

下载MNIST数据集并使用python将数据转换成NumPy数组(源码解析)

下载MNIST数据集并使用python将数据转换成NumPy数组首先来分析init_mnist函数接下来继续分析load_mnist函数实现数据集转换的python脚本的代码显示MNIST图像并确认数据 下载MNIST数据集并将数据转换成NumPy数组的Python脚本里面最重要的就是load_mnist函数,其他项目想要调用数据集的话,就可以调用load_mnist函数,得到一个字典类型的数据,字典的值是一个Numpy数组。 这些过程是如何实现的,现在开始逐字逐句分析源码: 在load_mnist函数中第

及时总结 4268

CMake终极加速指南:如何用远程缓存将编译时间减少80%

**CMake远程缓存**技术是现代C++开发中提升编译效率的终极解决方案。通过ccache和sccache等编译缓存工具,开发者可以轻松实现分布式编译加速,让团队协作开发效率飙升! CMake作为最流行的跨平台构建系统,支持多种**编译缓存工具**,能够显著减少重复编译时间。无论你是个人开发者还是大型团队,掌握**CMake远程缓存**技巧都能让你的开发工作流更加高效。🚀 ## 什么是CM

gitblog_00761的博客 914

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

MtBird vs 传统开发:为什么无代码平台能节省80%页面构建时间?

在当今快速变化的数字化时代,企业需要快速构建和迭代网页应用、小程序和H5页面来应对市场变化。传统开发方式往往需要数周甚至数月的时间,而MtBird无代码平台通过可视化拖拽操作,让页面构建时间缩短了惊人的80%!🎉 MtBird是一款强大的低代码可视化页面生成器,帮助用户无需编写代码或仅需少量代码即可快速创建网页、小程序和表单等应用。这款无代码编辑器通过拖拽式操作和可视化配置,彻底改变了传统开发

gitblog_00112的博客 616

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

对比传统虚拟机:Docker+GitLab如何节省80%构建时间

最近在优化团队CI/CD流程时,发现传统虚拟机跑GitLab流水线的构建时间越来越长。为了量化改进效果,我开发了一个构建时间对比工具,实测数据显示Docker容器能节省80%以上的构建时间。传统虚拟机运行GitLab Runner时,每次构建都需要从头安装依赖、编译环境,不仅耗时且资源利用率低。的在线Go环境,我快速完成了原型开发,其内置的依赖管理让工具可以一键运行测试,省去了本地配环境的麻烦。对于需要持续运行的服务类项目,平台的一键部署功能(如下图)也让demo分享变得特别方便。

EmeraldWolf23的博客 652

Docker --from用法全解析:如何通过多阶段构建将镜像体积减少80%

掌握Docker多阶段构建--from用法,有效减少镜像体积达80%。适用于微服务、CI/CD等场景,通过分阶段复制文件实现精简。详解各阶段依赖管理与镜像层优化技巧,提升构建效率与安全性,值得收藏。

AlgoPerch的博客 732

终极指南:zxcvbn构建优化5大实用技巧,轻松减少bundle体积80%

zxcvbn是Dropbox开发的密码强度评估库,通过模式匹配和保守估计来识别和评估密码的安全性。作为现代Web应用中的重要安全组件,zxcvbn能识别3万多个常见密码、姓名、流行英语单词以及常见模式。然而,由于其包含大量字典数据,未优化的zxcvbn构建可能导致bundle体积高达820KB,严重影响页面加载性能。🚀 本文将分享5个实用的zxcvbn构建优化技巧,帮助您大幅减小bundle体

gitblog_00060的博客 569

对比传统开发:AI生成OpenWeatherMap集成代码省时80%

通过这次实践,我深刻认识到AI辅助开发在效率上的巨大优势。特别是对于常规的API集成场景,使用InsCode(快马)平台可以节省大量重复劳动,让开发者专注于更有价值的创新工作。一键部署功能更是让成果可以立即上线测试,整个开发流程变得异常顺畅。对于需要快速原型开发或者中小型项目,这种开发方式无疑是更好的选择。即使是经验丰富的开发者,也能从中获得效率提升,把宝贵的时间用在更需要创造力的地方。

CyanWave34的博客 516

构建时间缩短80%,只因掌握了这个COPY缓存黑科技

掌握Docker镜像的COPY缓存技巧,显著提升构建效率。通过优化文件复制顺序与缓存层复用,减少重复构建开销,适用于高频迭代的微服务场景。构建时间缩短80%的秘密就在这里,值得收藏。

VarFlow的博客 659
上一篇: ChatGPT与这一代互联网人的未来
下一篇: 开源方案复现ChatGPT流程!1.62GB显存即可体验,单机训练提速7.73倍
职言职语
博客等级 码龄6年 6732粉丝 11原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值