Dockerfile的COPY --link

文章目录

  • 总结
  • 环境
  • 概述
  • “ --link” 是什么
  • 引入“ --link”
  • 使用“COPY --link”
  • 示例
  • 什么情况不适用
  • 总结
  • 参考

注:我做了很多测试,发现不管是否使用 --link ,结果貌似都一样。我在网上搜了半天,最后发现,该功能貌似目前被disable了,参见 https://github.com/docker/buildx/issues/1099 。等什么时候可用了,做完测试,再来完善该文章。

总结

  • 优点
    • 时间:独立的layer,提高了缓存的复用性,节省时间
    • 空间:向registry里push的image里只包含必要的layer,节省空间
    • cache-tocache-from :todo
  • 局限
    • 不能依赖于前面layer的文件系统
    • symlink

环境

  • RHEL 9.3
  • Docker Community 24.0.7

概述

COPY --link 是BuildKit的新功能,用来加速Docker image构建。它把文件复制到独立的image layer,并不需要上一步的layer存在。可以在base image不存在的情况下,为image添加新的内容。

该功能在作为Buildx v0.8的一部分,添加于2022年3月。Docker CLI的20.10.14版本包含了该功能。

“ --link” 是什么

--link 是Dockerfile的 COPY 指令的一个选项。

传统的 COPY 语句把文件复制到前一个layer里,该layer必须已存在,然后把新的内容合进来。

下面是一个传统的Dockerfile:

FROM alpine
COPY my-file /my-file
COPY another-file /another-file
  • FROM 指令之后,image包含了Alpine的内容:
bin/
dev/
etc/
......
  • 第一个 COPY 指令创建了一个image,包含了Alpine的内容以及 my-file 文件:
my-file
bin/
dev/
etc/
......
  • 同理,第二个 COPY 指令在该image之上,添加了 another-file 文件:
another-file
my-file
bin/
dev/
etc/
......

每条指令所创建的layer,包含了之前的所有东西和本指令新加的内容。在构建完成时,Docker使用一个“diff”进程检测出每个layer的变化。最终的image仅包含了在每个快照stage所添加的文件,但这并没有在构建的装配过程中体现出来(注:我理解这句话的意思是说,构建过程有一些冗余的东西)。

引入“ --link”

每次使用 --link 时,Docker会创建一个新的单独的文件系统。新文件不再复制到上一个layer里,而是复制到一个完全不同的位置,形成一个独立的layer。这些layer随后被链接在一起,产生最终的image。

下面是使用了 --link 的Dockerfile:

FROM alpine
COPY --link my-file /my-file
COPY --link another-file /another-file
  • FROM 指令不变,仍然创建了Alpine layer,包含了该image的所有内容:
bin/
dev/
etc/
......
  • 第一条 COPY 指令这次创建了一个独立的layer,它是一个仅包含 my-file 文件的新的文件系统:
my-file
  • 同理,第二条 COPY 指令也创建了另一个新的快照,其中只包含 another-file 文件:
another-file

当构建完成时,Docker把这些独立的快照保存为新的layer archive(tarball)。这些tarball被链接回之前的layer链里,构建出最终的image。它由这三个快照组合在一起。当创建容器时,其文件系统和原先(不用 --link 时)是一致的:

my-file
another-file
bin/
dev/
etc/
......

下图展示了这两种工作方式的不同:

在这里插入图片描述

使用“COPY --link”

COPY --link 只有在使用BuildKit构建image时才可以使用:

  • 使用 docker buildx --create 构建,或者:
  • 构建时设置环境变量 DOCKER_BUILDKIT=1

此外,必须指定Dockerfile v1.4语法。

# syntax=docker/dockerfile:1.4
FROM alpine:latest
COPY --link my-file /my-file
COPY --link another-file /another-file

构建:

DOCKER_BUILDKIT=1 docker build -t my-image:latest .

构建好的image并无差异, --link 只影响构建过程。

示例

使用 --link ,即使复制的内容发生变化,也可以复用build cache。此外,即使base image不存在,也可以完成构建。

回到上面的例子。在添加新内容之前,标准的 COPY 行为要求 alpine image必须已存在于宿主机上。如果之前没有pull过,则在构建时,该image会自动下载。

对于链接复制,Docker则不需要 alpine image里的内容。它pull alpine 的manifest,为复制的文件创建新的独立layer,然后创建一个修订版的manifest,把这些layer链接到alpine的layer里。只有从新的image启动容器,或者导出tar achive时,alpine image的内容才会下载。当你push新image到registry时,registry只存储该image的新layer,并从远端获取alpine的layer。

该功能也有利于高效的image rebase。你可能正在使用当时最新的Ubuntu 20.04 LTS做Docker image:

FROM golang AS build
...
RUN go build -o /app .FROM ubuntu:20.04
COPY --link --from=build /app /bin/app
ENTRYPOINT ["/bin/app"]

下面是一个完整的例子:

当前目录结构如下:

tree
.
├── Dockerfile
└── gotest1├── go.mod└── hello.go1 directory, 3 files
  • go.mod 文件如下:
module test1go 1.21.6
  • hello.go 文件如下:
package mainimport "fmt"func main() {fmt.Println("Hello, World!")
}
  • Dockerfile 文件如下:
FROM golang AS build
WORKDIR /myproject
RUN --mount=type=bind,source=gotest1,target=gotest1 cd gotest1 && go build -o /app .FROM ubuntu:20.04
COPY --link --from=build /app /bin/app
ENTRYPOINT ["/bin/app"]

在建构image时,你可以使用BuildKit的 --cache-to 选项来启用缓存。 inline 缓存在输出image里存储了构建的缓存数据,以便在后续的构建中重用。

docker buildx build --cache-to type=inline -t kaigotest1:20.04 .

注: buildx 可省略。

运行容器:

docker run kaigotest1:20.04
Hello, World!

假设,后来你想要使用Ubuntu 22.04:

FROM ubuntu:22.04

重新构建image时,可使用之前版本里嵌入的缓存数据:

docker buildx build --cache-from kaigotest1:20.04 -t kaigotest1:22.04 .

构建几乎瞬间就完成了。通过使用已有image里的缓存数据,Docker会验证构建 /app 的文件没有发生变化。这就意味着,通过 COPY 指令所创建的独立layer里的缓存仍然有效。由于该layer不依赖于其它layer, ubuntu:22.04 image也不会被pull下来。Docker仅仅在 ubuntu:22.04 layer链里,把包含 /bin/app 的快照layer链接到一个新的manifest里。快照layer被高效的“rebase”于一个新的parent image,而无需对文件系统的操作。

运行容器:

docker run kaigotest1:22.04
Hello, World!

该模型也可以优化multi-stage构建,其中任意stage之间都可能发生变化。

FROM golang AS build
RUN go build -o /app .FROM config-builder AS config
RUN generate-config --out /config.yamlFROM ubuntu:latest
COPY --link --from=config /config.yaml build.conf
COPY --link --from=build /app /bin/app

若没有 --link ,则产生的 config.yaml 文件的任何变化,都会导致 ubuntu:latest 被pull以及文件被复制。由于文件系统变化,造成缓存无效,还得重新编译。有了链接复制, config.yaml 文件的变化不会导致pull ubuntu:latest 或者重新编译。包含 build.conf 的快照layer简单的被替换为一个新的版本,这与其它layer是无关的。

什么情况不适用

有些情况下不适用 --link 选项。由于文件复制到一个新的layer,而不是添加到上一个layer里,所以在目标路径里,不能使用模糊引用(注:意指既可能是目录,也可能是文件,参见下面解释):

COPY --link my-file /data

在传统的 COPY 指令里,如果 /data 是image里已存在的一个目录,则 my-file 被复制为 /data/my-file 文件。而如果使用了 --link ,则目标layer的文件系统一定是空的,所以 my-file 一定会被复制到 /data 文件。

symlink(意指Linux的软链接文件)解析也有同样的考虑。标准的 COPY 指令会自动解析symlink的目标路径。而如果使用 --link ,则不支持该行为,因为symlink在copy的独立layer里不存在。

当没有遇到上述问题时,推荐使用 --link 。该功能会加速构建,并使得缓存更强大。由于这些非向后兼容的变化, --link 是一个选项(需显式指定),而不是缺省的功能。

总结

BuildKit的 COPY --link 使得构建更快更高效。使用链接复制的image无需pull之前的layer,仅仅是把文件复制过来。Docker会为每个 COPY 指令创建一个新的独立layer,然后把这些layer链接回layer链里。

参考

  • https://docs.docker.com/engine/reference/builder/#copy---link
  • https://www.howtogeek.com/devops/how-to-accelerate-docker-builds-and-optimize-caching-with-copy-link
  • https://www.docker.com/blog/image-rebase-and-improved-remote-cache-support-in-new-buildkit (讲的非常清楚。另:文中貌似有个typo: COPY --from=build --link /out/myapp /bin 目标路径最后应该加上 /
  • https://github.com/docker/buildx/issues/1099

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/620927.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SpringCloud:Ribbon

文章目录 Ribbon快速入门Ribbon负载均衡算法常见的负载均衡算法更改算法规则修改配置 饥饿加载 Ribbon ribbon是一个客户端负载均衡器,会从注册中心拉取可用服务,当客户端需要获取服务请求时,ribbon能够解析服务地址并实现负载均衡 快速入门 …

理解TCP/IP协议

一、协议 在计算机网络与信息通讯领域里,人们经常提及 “协议” 一词。互联网中常用的协议有HTTP、TCP、IP等。 协议的必要性 简单来说,协议就是计算机与计算机之间通过网络通信时,事先达成的一种 “约定”。这种“约定”使不同厂商的设备…

Linux工具-搭建文件服务器

当我们使用linux系统作为开发环境时,经常需要在Linux系统之间、Linux和Windows之间传输文件。 对少量文件进行传输时,可以使用scp工具在两台主机之间实现文件传输: rootubuntu:~$ ssh --help unknown option -- - usage: ssh [-46AaCfGgKkMN…

EndNote快速上手

前言:用EndNote主要就是为了方便管理文章引用的文献,所以本篇就是针对EndNote在文章中引用文献需要的技巧,然后本文用的是EndNoteX9。 EndNote快速上手 创建文献资料库创建文献分组导入文献手动输入文件导入在线搜索 修改文献信息去重文献删除…

详解Java之Spring框架中事务管理的艺术

第1章:引言 大家好,我是小黑,咱们今天聊聊Spring框架中的事务管理。不管是开发小型应用还是大型企业级应用,事务管理都是个不可避免的话题。那么,为什么事务管理这么重要呢?假设在银行系统中转账时&#x…

06-微服务OpenFeigh和Sentinel持久化

一、OpenFeign基础应用 1.1 概念 OpenFeign是一种声明式、模板化的HTTP客户端。在Spring Cloud中使用OpenFeign,可以做到使用HTTP请求访问远程服务,就像调用本地方法一样的,开发者完全感知不到这是在调用远程方法,更感知不到在访…

VITS(Conditional Variational Autoencoder with Adversarial Learning)论文解读及实现(一)

此篇为VITS论文解读第一部份 论文地址Conditional Variational Autoencoder with Adversarial Learning for End-to-End Text-to-Speech模型使用了VAE,GAN,FLOW以及transorflomer(文本处理有用到),即除了未diffusion模型,将生成式模型都融入进来了&#…

064:vue中一维数组的全选、全不选、反选(图文示例)

第061个 查看专栏目录: VUE ------ element UI 专栏目标 在vue和element UI联合技术栈的操控下,本专栏提供行之有效的源代码示例和信息点介绍,做到灵活运用。 (1)提供vue2的一些基本操作:安装、引用,模板使…

DHCP中继【新华三】

理论【DHCP服务器可以对其直连的网段中的pc,分配其IP地址等服务,但是,对于跨网段进行分配IP地址,需要中间有DHCP中继进行传达,由DHCP中继指定DHCP服务器的位置,可以很好的对其跨网段分配IP地址起到指引的作…

限时福利,Adobe InCopy2024下载安装指南

Adobe InCopy 下载链接 https://pan.baidu.com/s/16j5MiXqfGw6puQbgyQnJSQ?pwd0531 #2024版本 1.鼠标右击【InCopy2024(64bit)】压缩包(win11及以上系统需先点击“显示更多选项”)【解压到 InCopy2024(64bit)】。 2.打开解压后的文件夹,鼠…

Kubernetes 1.24正式发布,2022年首个大版本更新

介绍 早在 2020 年 12 月,Kubernetes 就宣布弃用 Dockershim。在 Kubernetes 中,dockershim 是一个软件 shim,它允许您将 Docker 引擎用作 Kubernetes 中的容器运行时。 这个版本包含 46 个增强功能:14 个增强功能已经升级到稳定…

【软件测试】学习笔记-设计GUI自动化测试策略

这篇文章从“实战”这个角度展开,探讨实际的大型全球化电商网站的GUI自动化测试如何开展。这场实战,从以下两个方面展开: 测试策略如何设计?这一点,我会根据亲身经历的实际项目,和你探讨GUI测试的分层测试…

Leetcode26——引出c++ vector中erase()的内部原理

erase是对数组中某个元素进行删除的操作,实际的时间复杂度为O(n) 预备知识 数组在内存中是连续存储的,删除某个位置的时候不能直接删除,只能用后序的元素覆盖 以nums数组为例,target为需要删除的目标数据 方法: ①…

codeforces (C++ Satisfying Constraints)

题目: 翻译: 思路: 1、找到最大的下限min 2、找到最小的上限max 3、则max-min1满足1、2约束条件的个数 4、max-min1减去约束条件3的个数,即为最终答案 5、如果min大于max,则结果为0,不存在满足约束条件的数…

【天龙怀旧服】攻略day7

关键字: 新星1.49、金针渡劫、10灵 1】新星(苍山破煞) 周三周六限定副本,19.00-24.00 通常刷1.49w,刷149点元佑碎金 boss选择通常为狂鬼难度,八风不动即放大不选,第二排第一个也不选&#xf…

RSIC-V“一芯”学习笔记(二)——Linux入门教程

文章目录 一、前言二、Busybox套件三、重要的追踪工具——strace四、Shell五、正则表达式六、重定向(多次输入测试时)七、一些组合命令八、自动化脚本九、学会查阅十、亲(yuan)近(li) bai du十一、不要逃避困难十二、重视小问题 一…

Grounding DINO:开放集目标检测,将基于Transformer的检测器DINO与真值预训练相结合

文章目录 背景知识补充CLIP (Contrastive Language-Image Pre-training):打破文字和图像之间的壁垒DINO(Data-INterpolating Neural Network):视觉 Transformer 的自监督学习Stable Diffusion:从文本描述中生成详细的图像Open-set Detector开…

【教3妹学编程-算法题】最大频率元素计数

2哥 : 3妹,最近有个电视剧《繁花》非常火🔥,你听说了吗? 3妹:没有,最近一直在忙着找工作,哪有时间看电视啊 2哥 : 啊?大周末还不休息一下啊,这么辛苦。 3妹:当…

Video接口介绍

屏库 https://m.panelook.cn/index_cn.php Open LDI, open lvds display interface OpenLDI and LVDS是兼容的, 是一种电平 https://www.ti2k.com/178597.html MIPI DSI/Camera crosLink FPD-LINK(Flat panel display link)是National(TI) LVDS技术, …

如何在线生成App:将网页封装成APP

在数字化时代,App已成为我们日常生活中不可或缺的一部分。然而,对于众多企业和个人开发者来说,开发一个原生App既耗时又耗资,尤其当他们已经拥有一个功能完备的网站时。幸运的是,现在有一种方法可以将现有的网页封装成…