了解 docker 层和未来的变化
Understanding docker layers and future changes
So,
Each Docker image references a list of read-only layers that represent filesystem differences. Layers are stacked on top of each other to form a base for a container’s root filesystem.
并且,
Because each container has its own thin writable container layer, and all changes are stored in this container layer, this means that multiple containers can share access to the same underlying image and yet have their own data state.
和also、
Layers of a Docker image are essentially just files generated from running some command. You can view the contents of each layer on the Docker host at /var/lib/docker/aufs/diff
.
现在,问题,
- 假设我构建我的 docker 图像 一层一层 。
A < B < C < D
,等等
- 现在,如果我 更新我的 docker 图片
A
,其余 docker 图片 B, C, D
会看到更改吗同样,前提是在构建它们时它们没有触及更改?例如,添加以前从未存在过的 /etc/apt/sources.list.d/somethingnew
。
- 如果我逐层构建 另一组 docker 图像。
A < X < Y < Z
,那么上面的变化也会反映在X, Y, Z
中,对吧?
- 但是,现在如果
A
的未来更改是 对同一个文件 进行的,在构建 B, C, D
时将更改该文件,那么会怎样发生?例如,让我们简化一下 docker 个图像 B, C, D
每个只在其层中添加 pkgB、pkgC 和 pkgD。如果我在构建 A
B, C, D
之后添加一个 pkgA,会发生什么? -- 我想对于一个系统,应该有一个单一版本的真实信息,如包中的内容,那么对于这种情况会是什么?
- 如果我只升级
A
中的软件包怎么办?这应该没问题吧? docker 图像的其余部分也会看到变化吗?
总的来说,每个图像都包含其 parent 图像,可以是嵌入字节,也可以是对本地缓存中图像的 "hard" 引用(如果它已经存在)。
"parent" 我的意思是 Docker 文件中的 FROM: someimage
指令。
我也写了 "hard" 因为参考实际上是 parent 图像的 sha246 摘要。如果 parent 的任何一位发生变化,摘要就会不同。
这里主要有三种情况:
您从清除缓存开始(docker image ls -a
什么也没显示)。如果您 docker pull ...
来自 public 注册表的一些图像,它将嵌入 parent。 docker ps -a
应该只显示一张图片。
如果您的缓存中已经有 parent 图像,docker pull ...
将不会再次下载 parent。在这种情况下,拉取的图像会引用缓存中的 parent。
如果您从清除缓存在本地构建,docker 将下载 parent 图像并生成一个 child 图像并引用 [=81] =].
最后还是一样的结果。如果您用更新版本替换 parent 图像,摘要将不一样。
Docker 不允许您删除其他图片引用的图片。当您将图像推送到注册表时,parent 会被嵌入(我在这里忽略了注册表端的缓存行为)。我认为您也可以使用 docker export
和 docker import
嵌入 parent,但我还没有尝试过。例如,docker export B
,然后从 docker 缓存中删除 A 和 B,然后 docker import B
应该只显示一张图像。
您可以使用
获得实际的 parent 关系
docker image inspect <image-id> | grep -E "Id|Parent"
将其与
合并
docker image ls -a --digests
检查关系。
更多信息。
构建映像时,会发生以下步骤:
- 构建上下文通过 docker 守护程序发送到主机。这基本上是您的 Docker 文件所在目录中的所有文件。这就是为什么使用
.dockerignore
只发送在您的 Docker 中复制的文件很重要文件。
- docker 守护程序使用 Docker 文件中的 FROM 指令创建一个临时容器。这是导入的图像,包括它自己的导入图像。然后 Dockefile 中的每条指令都在该容器内执行。当在临时容器中进行持久更改(如 COPY'ing)时,它会保存其状态。这有效地为最终图像添加了一层。
- DOCKERFILE 指令执行完毕后,临时容器将被销毁。您剩下的是最终图像。
您可以使用以下命令查看图像中的所有图层
docker history <image-id>
请注意,这提供了一种调试 Docker 文件的简便方法。您应该在 Docker 文件中看到与持久指令对应的层的 ID。您可以使用 docker run --rm -it <id next to layer> sh
从任何层创建一个新容器并手动执行后面的 Docker 文件指令。
So,
Each Docker image references a list of read-only layers that represent filesystem differences. Layers are stacked on top of each other to form a base for a container’s root filesystem.
并且,
Because each container has its own thin writable container layer, and all changes are stored in this container layer, this means that multiple containers can share access to the same underlying image and yet have their own data state.
和also、
Layers of a Docker image are essentially just files generated from running some command. You can view the contents of each layer on the Docker host at
/var/lib/docker/aufs/diff
.
现在,问题,
- 假设我构建我的 docker 图像 一层一层 。
A < B < C < D
,等等 - 现在,如果我 更新我的 docker 图片
A
,其余 docker 图片B, C, D
会看到更改吗同样,前提是在构建它们时它们没有触及更改?例如,添加以前从未存在过的/etc/apt/sources.list.d/somethingnew
。 - 如果我逐层构建 另一组 docker 图像。
A < X < Y < Z
,那么上面的变化也会反映在X, Y, Z
中,对吧? - 但是,现在如果
A
的未来更改是 对同一个文件 进行的,在构建B, C, D
时将更改该文件,那么会怎样发生?例如,让我们简化一下 docker 个图像B, C, D
每个只在其层中添加 pkgB、pkgC 和 pkgD。如果我在构建A
B, C, D
之后添加一个 pkgA,会发生什么? -- 我想对于一个系统,应该有一个单一版本的真实信息,如包中的内容,那么对于这种情况会是什么? - 如果我只升级
A
中的软件包怎么办?这应该没问题吧? docker 图像的其余部分也会看到变化吗?
总的来说,每个图像都包含其 parent 图像,可以是嵌入字节,也可以是对本地缓存中图像的 "hard" 引用(如果它已经存在)。
"parent" 我的意思是 Docker 文件中的 FROM: someimage
指令。
我也写了 "hard" 因为参考实际上是 parent 图像的 sha246 摘要。如果 parent 的任何一位发生变化,摘要就会不同。
这里主要有三种情况:
您从清除缓存开始(
docker image ls -a
什么也没显示)。如果您docker pull ...
来自 public 注册表的一些图像,它将嵌入 parent。docker ps -a
应该只显示一张图片。如果您的缓存中已经有 parent 图像,
docker pull ...
将不会再次下载 parent。在这种情况下,拉取的图像会引用缓存中的 parent。如果您从清除缓存在本地构建,docker 将下载 parent 图像并生成一个 child 图像并引用 [=81] =].
最后还是一样的结果。如果您用更新版本替换 parent 图像,摘要将不一样。
Docker 不允许您删除其他图片引用的图片。当您将图像推送到注册表时,parent 会被嵌入(我在这里忽略了注册表端的缓存行为)。我认为您也可以使用 docker export
和 docker import
嵌入 parent,但我还没有尝试过。例如,docker export B
,然后从 docker 缓存中删除 A 和 B,然后 docker import B
应该只显示一张图像。
您可以使用
获得实际的 parent 关系docker image inspect <image-id> | grep -E "Id|Parent"
将其与
合并docker image ls -a --digests
检查关系。
更多信息。
构建映像时,会发生以下步骤:
- 构建上下文通过 docker 守护程序发送到主机。这基本上是您的 Docker 文件所在目录中的所有文件。这就是为什么使用
.dockerignore
只发送在您的 Docker 中复制的文件很重要文件。 - docker 守护程序使用 Docker 文件中的 FROM 指令创建一个临时容器。这是导入的图像,包括它自己的导入图像。然后 Dockefile 中的每条指令都在该容器内执行。当在临时容器中进行持久更改(如 COPY'ing)时,它会保存其状态。这有效地为最终图像添加了一层。
- DOCKERFILE 指令执行完毕后,临时容器将被销毁。您剩下的是最终图像。
您可以使用以下命令查看图像中的所有图层
docker history <image-id>
请注意,这提供了一种调试 Docker 文件的简便方法。您应该在 Docker 文件中看到与持久指令对应的层的 ID。您可以使用 docker run --rm -it <id next to layer> sh
从任何层创建一个新容器并手动执行后面的 Docker 文件指令。