了解 docker 层和未来的变化

xpt*_*xpt 4 ubuntu debian docker

所以

\n\n

在此输入图像描述

\n\n
\n

每个 Docker 映像都会引用代表文件系统差异的只读层列表。各层相互堆叠,形成容器\xe2\x80\x99s 根文件系统的基础。

\n
\n\n

和,

\n\n

在此输入图像描述

\n\n
\n

因为每个容器都有自己的薄可写容器层,并且所有更改都存储在该容器层中,这意味着多个容器可以共享同一底层映像的访问,但又拥有自己的数据状态。

\n
\n\n

并且,

\n\n
\n

Docker 镜像的各层本质上只是运行某些命令生成的文件。您可以在 Docker 主机上查看各层的内容/var/lib/docker/aufs/diff

\n
\n\n

现在,问题,

\n\n
    \n
  • 假设我逐层构建我的 docker 镜像。A < B < C < D, ETC。
  • \n
  • 现在,如果我更新我的 docker 映像 A,那么其余的 docker 映像也会B, C, D看到这些更改吗?前提是它们在构建时没有触及这些更改?例如,添加/etc/apt/sources.list.d/somethingnew以前从未有过的内容。
  • \n
  • 如果我一层一层地构建了另一组docker 镜像。A < X < Y < Z,那么上面的变化也会体现出来X, Y, Z吧?
  • \n
  • 但是现在,如果将来对 , 的更改A是对构建 时将更改的同一文件进行的B, C, D,那么会发生什么?例如,让我们简单一点,B, C, D每个 docker 镜像仅在其层中添加 pkgB、pkgC 和 pkgD。如果我在构建A 添加 pkgA ,会发生什么?B, C, D-- 我想对于单个系统,对于软件包所在的情况应该有一个单一的事实版本,那么对于这种情况会是什么?
  • \n
  • 如果我只升级中的软件包怎么办A?这应该没问题吧?其余的 docker 镜像也会看到这些变化吗?
  • \n
\n

Ber*_*ard 5

总的来说,每个图像都包含其父图像,要么作为嵌入字节,要么作为对本地缓存中图像的“硬”引用(如果该图像已存在)。

我所说的“父级”是指FROM: someimageDockerfile 中的指令。

我还写了“hard”,因为引用实际上是父图像的 sha246 摘要。如果父级的任何一点发生变化,摘要都会有所不同。

这里主要分为三种情况:

  1. 您从清除缓存开始(docker image ls -a什么也不显示)。如果您docker pull ...从公共注册表中获取某些图像,它将嵌入其父级。Adocker ps -a应该只显示一张图像。

  2. 但是,如果您的缓存中已有父图像,则docker pull ...不会再次下载父图像。在这种情况下,拉取的图像具有对缓存中父级的引用。

  3. 如果您从清晰的缓存在本地构建,docker 将下载父映像并生成一个引用父映像的子映像。

最后还是一样的结果。如果您将父映像替换为较新的版本,则摘要将不一样。

如果另一个镜像引用了某个镜像,Docker 不会让你删除该镜像。当您将图像推送到注册表时,父级会被嵌入(我在这里略过注册表端的缓存行为)。我认为您也可以使用docker exportand嵌入父级docker import,但我还没有尝试过。例如,docker export B然后从 docker 缓存中删除 A 和 B,并且docker import B应该只显示一张图像。

您可以使用以下方式获取实际的父关系

docker image inspect <image-id> | grep -E "Id|Parent"
Run Code Online (Sandbox Code Playgroud)

将其与

docker image ls -a --digests
Run Code Online (Sandbox Code Playgroud)

来检查关系。

更多信息。

当您构建镜像时,会发生以下步骤:

  1. 构建上下文通过 docker 守护进程发送到主机。这基本上是 Dockerfile 所在目录中的所有文件。这就是为什么.dockerignore仅发送在 Dockerfile 中复制的文件很重要。
  2. docker 守护进程使用 Dockerfile 中的 FROM 指令创建临时容器。这是导入的图像,包括它自己导入的图像。然后,Dockefile 中的每条指令都会在该容器内执行。当在临时容器中进行持久更改(例如复制)时,它会保存其状态。这有效地为最终图像添加了一层。
  3. 一旦执行完 DOCKERFILE 指令,临时容器就会被销毁。剩下的就是最终的图像。

您可以使用以下命令查看图像中的所有图层 docker history <image-id>

请注意,这提供了一种调试 Dockerfile 的便捷方法。您应该会看到与 Dockerfile 中的持久指令相对应的层的 ID。docker run --rm -it <id next to layer> sh您可以使用以下 Dockerfile 指令从任何层创建新容器并手动执行。