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,一经查实,立即删除!

相关文章

计算机网络的常用的网络通信命令(Windows)

ping:它是用来检查网络是否通畅或者网络连接速度的命令。ping命令利用的原理是:网络上的机器都有唯一确定的IP地址,我们给目标IP地址发送一个数据包,对方就要返回一个同样大小的数据包,根据返回的数据包我们可以确定目…

父(子)组件获取子(父)组件的方法和数据

1.父组件获取子组件的方法和数据 在父组件中的子组件添加 ref"childName"&#xff0c;childName自定义 <childComponent ref"childName"></childComponent> #获取子组件的方法 method:方法名this.$refs.childName.method()#获取子组件的数…

Linux——安装docker

安装 curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun启动docker systemctl start docker常用指令 查找镜像 docker search [name]拉取镜像 docker pull [name]运行容器 docker run [name] 配置项&#xff1a;-i 交互式 -t 终端 -d 后台运行 --name [n…

【力扣每日一题】力扣83删除排序链表中的重复元素

题目来源 力扣83删除排序链表中的重复元素 题目描述 给定一个已排序的链表的头 head &#xff0c; 删除所有重复的元素&#xff0c;使每个元素只出现一次 。返回 已排序的链表 。 思路分析 思路一&#xff1a;使用两个指针&#xff0c;last指针指向上一个元素&#xff0c;…

高中电学实验学习

bilibili上的笔记有价值的链接 1、 自学物理吧 电学实验 https://www.bilibili.com/video/BV1SM411u757/?spm_id_from333.337.search-card.all.click&vd_source91b03ee59c462b7b3cfbd57346cf1001 2、张老师的物理课堂 测电源电动势和内阻

Unity求射线与球体交点(有可能还能优化)

代码如下&#xff1a; bool RayCrossSphere(Ray ray, Sphere sphere, out Vector3[] vs) {Vector3 c2o sphere.center - ray.origin;float sqrtRadius sphere.radius * sphere.radius;Vector3 project Vector3.Project(c2o, ray.direction);Vector3 vPoint ray.origin pr…

【驱动】TI AM437x(内核调试-02):dynamic 动态打印调试

1、配置内核 dynamic 可以根据不同级别的作用域来启用/禁用-每个源文件、函数、模块、格式字符串和行号的打印信息。 内核中,默认没有配置 dynamic ,因为使能 dynamic 会使内核增大2% Symbol: DYNAMIC_DEBUG [=n] Type : boolean …

SpringCloud:Ribbon

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

理解TCP/IP协议

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

Linux工具-搭建文件服务器

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

EndNote快速上手

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

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

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

__declspec(dllexport)与__declspec(dllimport) 的区别

__declspec(dllexport) 和 __declspec(dllimport) 是用于在 Windows 平台上定义导出和导入函数或变量的关键字。它们的作用如下&#xff1a; 1. __declspec(dllexport): 当您在定义一个函数或变量时使用__declspec(dllexport)关键字时&#xff0c;它告诉编译器将该函数或变量导…

06-微服务OpenFeigh和Sentinel持久化

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

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(文本处理有用到)&#xff0c;即除了未diffusion模型&#xff0c;将生成式模型都融入进来了&#…

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

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

openssl3.2 - 官方demo学习 - digest - EVP_MD_xof.c

文章目录 openssl3.2 - 官方demo学习 - digest - EVP_MD_xof.c概述笔记END openssl3.2 - 官方demo学习 - digest - EVP_MD_xof.c 概述 使用支持XOF方式的摘要算法(e.g. SHAKE256), 对buffer进行摘要, 并和预留的摘要值进行比对 笔记 /*! \file EVP_MD_xof.c \note openssl3…

DHCP中继【新华三】

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

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

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

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

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