dock er catch机制

2024-05-12 16:58
文章标签 机制 catch er dock

本文主要是介绍dock er catch机制,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

docker build 简介

众所周知,一个 Dockerfile 唯一的定义了一个 Docker 镜像。如此依赖,Docker 必须提供一种方式,将 Dockerfile 转换为 Docker 镜像,采用的方式就是 docker build 命令。以如下的 Dockerfile 为例:

 
  1. FROM ubuntu:14.04

  2. RUN apt-get update

  3. ADD run.sh /

  4. VOLUME /data

  5. CMD ["./run.sh"]

一般此 Dockerfile 的当前目录下,必须包含文件 run.sh。通过执行以下命令

docker build -t="my_new_image" .  

即可将当前目录下的 Dockerfile 构建成一个名为 my_new_image 的镜像,镜像的默认 tag 为 latest。对于以上的docker build请求,Docker Daemon 新创建了 4 层镜像,除了 FROM 命令,其余的 RUN、ADD、VOLUME 以及 CMD 命令都会创建一层新的镜像。

镜像 cache 机制介绍

Dockerfile 可以通过docker build命令构建为一个新的镜像,Dockerfile 中每一条命令都会构建出一个新的镜像层。既然如此,构建成功后宿主机上的镜像层是否会不断增多,导致磁盘空间资源逐渐缩小?另外,一个 Dockerfile 如果构建多次,对于 Dockerfile 中的某一指定命令,是否会出现产生多个对应镜像层的情况呢?

镜像层的增多自然是毋庸置疑,然而并非每一次构建的每一条 Dockerfile 命令都会产生一个全新的镜像层。谈及原因,那我们必须谈谈 docker build 的 cache 机制。

docker build 的 cache 机制: Docker Daemnon 通过 Dockerfile 构建镜像时,当发现即将新构建出的镜像与已有的某镜像重复时,可以选择放弃构建新的镜像,而是选用已有的镜像作为构建结果,也就是采取本地已经 cache 的镜像作为结果。

反复阅读以上解释,细心的朋友肯定会有两点疑惑:

1. “即将构建出的镜像”属于仍未构建完成的镜像,通过何种方式来标识此镜像?

2. 涉及到镜像比较,重复时选择放弃构建,那镜像比较时重复的标准是什么?

cache 机制实现原理

Docker 镜像,由镜像层文件系统内容镜像 json文件组成,而这两者都含有一个相同的镜像 ID 。还记得我们之前谈及的父镜像子镜像的概念吗?此处也会大量运用镜像间的父子关系。

还是以上文中的 Dockerfile 为例,我们结合下图,着重分析命令 FROM ubuntu:14.04 和 RUN apt-get update

image

FROM ubuntu:14.04: FROM 命令是 Dockerfile 中唯一不可缺少的命令,它为最终构建出的镜像设定了一个基础镜像(base image)。docker build命令解析 Dockerfile 的 FROM 命令时,可以立即获悉在哪一个镜像基础上完成下一条命令RUN apt-get update的镜像构建。此时,Docker Daemon 获取 ubuntu:14.04 镜像的镜像 ID,并提取该镜像 json 文件中的内容,以备下一条命令构建时使用。

RUN apt-get update:RUN 命令是在上一层镜像(即 ubuntu:14.04 镜像)之上运行 apt-get update,所有对文件系统内容有更新的文件,都会保留于新构建的镜像层中,同时更新上一层镜像的 json 文件,更新镜像 json 文件的 Cmd 属性为"/bin/sh -c apt-get update"。注意:镜像 json 文件的 Cmd 属性与镜像 json 文件中 config 属性的 Cmd 属性,详见下图 RUN 命令所对应镜像(镜像 ID 为:0aaab7ef57ee)中两个 Cmd 的区别:

image

完成一条非 FROM 命令的构建,即产生一个新的镜像,新的镜像为其上一条命令产生镜像的子镜像。基于此以及以上的知识,我们可以提出这样的一个猜想:

“是否可以在构建 Dockerfile 某一命令前,就预知即将构建出新一层镜像的形态?”

围绕此问题,我们继续分析。未构建命令 RUN apt-get update 前,我们可以肯定的事实有以下几点:

  • 镜像关系:对于命令RUN apt-get update的构建,一定将会产生一个新镜像,新镜像的父镜像 ID 为 ubuntu:14.04 的镜像 ID,即 8251da35e7a7。

  • 镜像 json 文件更新:运行命令 apt-get update 后产生新镜像,新镜像 json 文件仅仅更新 ubuntu:14.04 镜像 json 文件的 Cmd 属性,其它如 config 属性均不会进行修改。

  • 镜像层文件系统内容更新:运行 apt-get update 后,对于容器可读写层的内容更新,全部将被打包进新镜像的镜像层文件系统内容。

基于这 3 个事实,我们再提出一个假设:如果在构建命令 RUN apt-get update 前,Docker Daemon 已经存在一个镜像满足以下两点:

  • 此镜像的父镜像为 ubuntu:14.04
  • 此镜像的 json 文件仅仅将 ubuntu:14.04 镜像 json 文件的 Cmd 属性更新为 apt-get update

那么是否可以认为:即将新构建的镜像与此镜像完全一致,不需要另行构建,只需复用此镜像即可?

如果你认可以上假设,那么 cache 机制的核心就接近浮出水面了:遍历本地所有镜像,发现镜像与即将构建出的镜像一致时,将找到的镜像作为 cache 镜像,复用 cache 镜像作为构建结果。

cache 机制注意事项

可以说,cache 机制很大程度上做到了镜像的复用,降低存储空间的同时,还大大缩短了构建时间。然而,不得不说的是,想要用好 cache 机制,那就必须了解利用 cache 机制时的一些注意事项。

1. ADD 命令与 COPY 命令:Dockerfile 没有发生任何改变,但是命令ADD run.sh / 中 Dockerfile 当前目录下的 run.sh 却发生了变化,从而将直接导致镜像层文件系统内容的更新,原则上不应该再使用 cache。那么,判断 ADD 命令或者 COPY 命令后紧接的文件是否发生变化,则成为是否延用 cache 的重要依据。Docker 采取的策略是:获取 Dockerfile 下内容(包括文件的部分 inode 信息),计算出一个唯一的 hash 值,若 hash 值未发生变化,则可以认为文件内容没有发生变化,可以使用 cache 机制;反之亦然。

2. RUN 命令存在外部依赖:一旦 RUN 命令存在外部依赖,如RUN apt-get update,那么随着时间的推移,基于同一个基础镜像,一年的 apt-get update 和一年后的 apt-get update, 由于软件源软件的更新,从而导致产生的镜像理论上应该不同。如果继续使用 cache 机制,将存在不满足用户需求的情况。Docker 一开始的设计既考虑了外部依赖的问题,用户可以使用参数 --no-cache 确保获取最新的外部依赖,命令为docker build --no-cache -t="my_new_image" .

3. 树状的镜像关系决定了,一次新镜像的成功构建将导致后续的 cache 机制全部失效:这一点很好理解,一旦产生一个新的镜像,同时意味着产生一个新的镜像 ID,而当前宿主机环境中肯定不会存在一个镜像,此镜像 ID 的父镜像 ID 是新产生镜像的ID。这也是为什么,书写 Dockerfile 时,应该将更多静态的安装、配置命令尽可能地放在 Dockerfile 的较前位置。

总结

docker build 的 cache 机制实现了镜像的复用,不仅节省了镜像的存储空间,也为镜像构建节省了大量的时间。 同时,如何命中 cache 镜像,也是衡量 Dockerfile 书写是否合理的重要标准之一。

这篇关于dock er catch机制的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/983202

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Java ArrayList扩容机制 (源码解读)

结论:初始长度为10,若所需长度小于1.5倍原长度,则按照1.5倍扩容。若不够用则按照所需长度扩容。 一. 明确类内部重要变量含义         1:数组默认长度         2:这是一个共享的空数组实例,用于明确创建长度为0时的ArrayList ,比如通过 new ArrayList<>(0),ArrayList 内部的数组 elementData 会指向这个 EMPTY_EL

【编程底层思考】垃圾收集机制,GC算法,垃圾收集器类型概述

Java的垃圾收集(Garbage Collection,GC)机制是Java语言的一大特色,它负责自动管理内存的回收,释放不再使用的对象所占用的内存。以下是对Java垃圾收集机制的详细介绍: 一、垃圾收集机制概述: 对象存活判断:垃圾收集器定期检查堆内存中的对象,判断哪些对象是“垃圾”,即不再被任何引用链直接或间接引用的对象。内存回收:将判断为垃圾的对象占用的内存进行回收,以便重新使用。

【Tools】大模型中的自注意力机制

摇来摇去摇碎点点的金黄 伸手牵来一片梦的霞光 南方的小巷推开多情的门窗 年轻和我们歌唱 摇来摇去摇着温柔的阳光 轻轻托起一件梦的衣裳 古老的都市每天都改变模样                      🎵 方芳《摇太阳》 自注意力机制(Self-Attention)是一种在Transformer等大模型中经常使用的注意力机制。该机制通过对输入序列中的每个元素计算与其他元素之间的相似性,

如何通俗理解注意力机制?

1、注意力机制(Attention Mechanism)是机器学习和深度学习中一种模拟人类注意力的方法,用于提高模型在处理大量信息时的效率和效果。通俗地理解,它就像是在一堆信息中找到最重要的部分,把注意力集中在这些关键点上,从而更好地完成任务。以下是几个简单的比喻来帮助理解注意力机制: 2、寻找重点:想象一下,你在阅读一篇文章的时候,有些段落特别重要,你会特别注意这些段落,反复阅读,而对其他部分

【Tools】大模型中的注意力机制

摇来摇去摇碎点点的金黄 伸手牵来一片梦的霞光 南方的小巷推开多情的门窗 年轻和我们歌唱 摇来摇去摇着温柔的阳光 轻轻托起一件梦的衣裳 古老的都市每天都改变模样                      🎵 方芳《摇太阳》 在大模型中,注意力机制是一种重要的技术,它被广泛应用于自然语言处理领域,特别是在机器翻译和语言模型中。 注意力机制的基本思想是通过计算输入序列中各个位置的权重,以确

FreeRTOS内部机制学习03(事件组内部机制)

文章目录 事件组使用的场景事件组的核心以及Set事件API做的事情事件组的特殊之处事件组为什么不关闭中断xEventGroupSetBitsFromISR内部是怎么做的? 事件组使用的场景 学校组织秋游,组长在等待: 张三:我到了 李四:我到了 王五:我到了 组长说:好,大家都到齐了,出发! 秋游回来第二天就要提交一篇心得报告,组长在焦急等待:张三、李四、王五谁先写好就交谁的

UVM:callback机制的意义和用法

1. 作用         Callback机制在UVM验证平台,最大用处就是为了提高验证平台的可重用性。在不创建复杂的OOP层次结构前提下,针对组件中的某些行为,在其之前后之后,内置一些函数,增加或者修改UVM组件的操作,增加新的功能,从而实现一个环境多个用例。此外还可以通过Callback机制构建异常的测试用例。 2. 使用步骤         (1)在UVM组件中内嵌callback函

Smarty模板引擎工作机制(一)

深入浅出Smarty模板引擎工作机制,我们将对比使用smarty模板引擎和没使用smarty模板引擎的两种开发方式的区别,并动手开发一个自己的模板引擎,以便加深对smarty模板引擎工作机制的理解。 在没有使用Smarty模板引擎的情况下,我们都是将PHP程序和网页模板合在一起编辑的,好比下面的源代码: <?php$title="深处浅出之Smarty模板引擎工作机制";$content=

Redis的rehash机制

在Redis中,键值对(Key-Value Pair)存储方式是由字典(Dict)保存的,而字典底层是通过哈希表来实现的。通过哈希表中的节点保存字典中的键值对。我们知道当HashMap中由于Hash冲突(负载因子)超过某个阈值时,出于链表性能的考虑,会进行Resize的操作。Redis也一样。 在redis的具体实现中,使用了一种叫做渐进式哈希(rehashing)的机制来提高字典的缩放效率,避