我们是如何将Docker构建时间缩短40%的

server/2024/10/18 8:28:10/

by: WL

Mapmost从设计之初,便选择了云原生道路,在软件开发过程中自然也少不了容器化技术的使用。当然,我们也为Mapmost产品中使用的所有组件构建了 docker 镜像。然而,随着时间的推移,其中一些镜像变得越来越大,CI 构建时间也越来越长。通过调研和总结经验,我们发现当构建时间超过5分钟时,会降低相关开发人员的工作效率。主要体现在以下两个方面:

  1. 开发人员如果一直等待构建完成,则浪费了大量时间;
  2. 开发人员如果去做新的事情,然后过一段时间再回来,这时候需要额外的上下文切换时间,通常也会导致效率下降。

那么接下来将为大家介绍2个构建小改动,可以大大缩短我们的构建时间。在此之前,我们已参考Docker官方给出的Dockerfile最佳实践编写了Dockerfile,如:

  1. 最小化层数
  2. 使用多阶段构建
  3. 使用最小基础映像

一、BuildKit vs Buildx

让我们首先了解下 Buildkit 和 Buildx,他们通常可以互换使用,但它们并不相同。

1. Buildkit

BuildKit 的诞生旨在取代Docker传统的构建引擎。自 Docker Desktop 以及 Docker Engine 23.0 版本起,BuildKit 成为默认构建器,其优化了构建过程的效率和性能,提供了许多新特性,如:

  • 更优的缓存能力
  • 并行构建
  • 基础镜像的懒拉取(≥ Buildkit 0.9)

如果需要在 23.0 之前的 docker 版本中使用 BuildKit,常见方法如下:

DOCKER_BUILDKIT=1 docker build --platform linux/amd64 . -t someImage:someTag
DOCKER_BUILDKIT=1 docker push someImage:someTag

2. Buildx

Buildx是Docker的一个插件,支持Buildkit的全部特性。Buildx的产生是因为Buildkit的许多新配置选项,无法向后兼容集成到docker build命令中。

除了提供构建镜像的功能,Buildx还可以管理多个构建器。在CI/CD中,我们使用同一个Docker就能很好的隔离具有不同配置的构建器,而以往我们常常需要在不同的Docker中构建。

如何创建并使用Buildx的基本操作如下:

docker buildx create --bootstrap --name builder
docker buildx use builder

二、 远程存储构建缓存信息

我们介绍的第一个方法:将镜像缓存在远程仓库。

这样,即使在不同机器上进行构建也会用到缓存,典型的使用场景正是在CI/CD中使用不同构建器构建各种镜像。当我们使用默认的构建器时,每个BuildKit实例仅能维护并使用自己的缓存。当在不同的构建器之间切换时,缓存不会共享。因此存在重复拉取镜像。但如果使用外部远程缓存特性,我们则可以指定用于推送和拉取镜像的远程位置,构建时会大大缩短时间。要使用外部缓存,通常指定 --cache-to 和 --cache-from 选项结合buildx。具体形式如下:

docker buildx build --platform linux/amd64 . \
-t someImage:someVersion - push \
--cache-to type=registry,ref=someCachedImage:someVersion,mode=max
--cache-from type=registry,ref=someCachedImage:someVersion

以上指令告诉构建器在someCachedImage:someVersion镜像中查找缓存。当构建完成后,新的构建缓存被推送到相同的镜像中, 覆盖旧缓存。mode=max 表示存储每一层的构建信息,即使是结果镜像中不使用的层(如多阶段构建时中间阶段产生的构建信息)。mode默认值为min,此时只存储结果图像中存在的层的构建信息。

三、添加、复制文件到镜像时使用link选项

dockerfile1.4语法开始,其对COPY和ADD指令增加了新的选项:--link

# syntax=docker/dockerfile:1.4
FROM ...
COPY --link foo bar

1.在没有使用--link选项时,将某个文件复制到某个目录,需要先完成所有前面的指令,即此时父层快照必须存在,构建器会将父层复制到新快照中,否则如果目录不存在,COPY指令将执行失败。在构建完导出结果镜像时,通过“differ”组件比较所有快照然后将它们合并,从而创建包含每个快照中添加的文件最终镜像文件。

2.通过设置 --link选项,COPY 指令会将文件复制到一个完全新的快照中,而不是基于父层进行添加。在最后生成结果镜像时,这个新快照也会被转换成一个单独层,该层会被链接到父层中。链接操作通常只是涉及一些元数据的更改,此时,构建器无需访问或移动任何文件。即使某些层存在于远程仓库中,也可以在不需拉取或推送它们的情况下远程完成这一操作。

使用该选项前后对比如下:

图源:https://www.docker.com/blog/image-rebase-and-improved-remote-cache-support-in-new-buildkit

使用--link选项的主要优势是文件不再依赖于父层。只要文件没有改变,即使父层改变了,自身层也可以被复用。得益于此,构建器能够并行执行多层复制数据,大大缩短构建时间。

在这篇文章中,我们介绍了在Mapmost产品开发中使用到的2个小技巧,这样就实现了整体的Docker构建时间减少40%。


Mapmost秉持着“让人与机器联合创作成为新常态”的理念,综合运用多项前沿技术,以SDK二次开发或零代码的方式为工厂、企业等提供一站式数字李生解决方案,现已广泛应用于各行业数字化项目建设。

点击这里跳转Mapmost官网体验


http://www.ppmy.cn/server/131330.html

相关文章

自动驾驶系列—自动驾驶系统中的ROS通信机制:原理、架构与核心技术

🌟🌟 欢迎来到我的技术小筑,一个专为技术探索者打造的交流空间。在这里,我们不仅分享代码的智慧,还探讨技术的深度与广度。无论您是资深开发者还是技术新手,这里都有一片属于您的天空。让我们在知识的海洋中…

400行程序写一个实时操作系统RTOS(开篇)

笔者之前突发奇想,准备写一个极其微小的实时操作系统内核,在经过数天的努力后,这个RTOS诞生了。令读者比较意外的是,它的程序只有400行左右。但就是这短短的400行,完成了动态内存管理、多线程、优先级、临界区、低功耗…

Android Studio开发Kotlin项目中遇到的问题解决集

背景&#xff1a;Android Studio 2022.3.1 1.Unexpected tokens (use ; to separate expressions on the same line) 无法在同一行声明一个变量并实例化。 解决&#xff1a;分开 &#xff08;1&#xff09; var aaCo:Runoob<String>aaCoRunoob("aa") &…

【数据泄露】万豪数据泄露事件:全球3.44亿客户信息外泄,5200万美元罚款背后的信息安全警钟

一、背景概述 近年来,全球范围内的网络安全问题频发,许多大型跨国公司也难以幸免。作为全球酒店业的领军者,万豪国际酒店集团因多起重大数据泄露事件深陷风波,涉及全球超过3.44亿客户的敏感信息泄露。2014年至2020年间,万豪接连遭遇三次严重的数据安全事件,暴露出公司在…

@controller注解和@RestController注解详解

文章目录 控制器MVC控制器REST 控制器 controllerRestController总结 控制器 MVC控制器 在了解这两种注解之前我们需要先知道控制器的概念&#xff0c;我们项目中常见的就是MVC控制器&#xff0c;MVC 是一种软件架构模式&#xff0c;它将应用程序分为三个主要组件&#xff1a;…

redistemplate宇jedis区别

redistemplate是Spring Data Redis提供的一个模板类&#xff0c;用于简化Redis操作的代码编写。它提供了常见的操作方法&#xff0c;如存储、读取、删除等&#xff0c;可以更方便地操作Redis数据库。 而Jedis是Redis官方推荐的Java客户端库之一。它提供了丰富的功能和灵活的接…

第十五届蓝桥杯C++B组省赛

文章目录 1.握手问题解题思路1&#xff08;组合数学&#xff09;解题思路2&#xff08;暴力枚举&#xff09; 2.小球反弹做题思路 3.好数算法思路&#xff08;暴力解法&#xff09;---不会超时 4.R格式算法思路 5.宝石组合算法思路---唯一分解定理 6.数字接龙算法思路----DFS 7…

健康生活的重要性

在当今快节奏的生活中&#xff0c;养生保健已成为人们日益关注的话题&#xff0c;而健身作为其中的重要一环&#xff0c;更是被赋予了前所未有的重视。谈及养生保健与健身&#xff0c;我们不得不深入思考&#xff1a;如何在繁忙的日常中&#xff0c;找到那条通往健康与活力的道…