了解Docker层和未来的变化 [英] Understanding docker layers and future changes

查看:130
本文介绍了了解Docker层和未来的变化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


每个Docker映像均引用了以下内容的列表:仅代表文件系统差异的层。各个层堆叠在一起,形成容器根文件系统的基础。


并且




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



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


现在,问题,




  • 说我逐层构建我的泊坞窗图像。 A< B < C < D 等。

  • 现在,如果我更新我的Docker映像 A ,其他docker images B,C,D 也会看到这些更改,但前提是在构建它们时不触及这些更改?例如,添加以前从未有过的 /etc/apt/sources.list.d/somethingnew

  • 如果我已经建造了另一组泊坞窗图像。 A< X < Y < Z ,那么上述更改也将反映在 X,Y,Z 中,对吗?

  • 现在,如果将来更改为 A ,将修改为同一文件生成 B,C,D 时发生了变化,那么会发生什么?例如,让我们简单起见,Docker图像 B,C,D 各自仅在其层中添加pkgB,pkgC和pkgD。如果在构建完B,C,D A 中添加了pkgA,会怎样?会发生? -我猜应该有一个单一版本的真理,因为对于单个系统,其中包含什么软件包,那么这种情况会是什么?

  • 如果我仅升级 A 中的软件包怎么办?这样应该可以吧?其余的Docker映像也会看到更改吗?


解决方案

总体而言,每个图像都包含其父图像,可以是嵌入式字节,也可以是

父是指 FROM:someimage

我也写了 hard,因为该引用实际上是父映像的sha246摘要。如果父级的任何一位更改,则摘要将有所不同。



这里主要有三种情况:


  1. 您从清晰的缓存( docker image ls -a 不显示任何内容)。如果您 docker pull ... 来自公共注册表的某些图像,它将嵌入其父级。 docker ps -a 应该只显示一个图像。


  2. 但是如果您已经有父图像在您的缓存中, docker pull ... 不会再次下载父项。在这种情况下,提取的映像在缓存中会引用父映像。


  3. 如果您是从纯缓存本地构建的,则docker将下载父映像。并生成参照父级的子级图像。


最后的结果仍然相同。如果您用较新的版本替换父映像,则摘要将不一样。



如果另一个映像引用了Docker,则Docker将不允许您删除该映像。当您将映像推送到注册表时,父项已嵌入(我在此处跳过了注册表方面的缓存行为)。我认为您也可以使用 docker export docker import 嵌入父级,但是我还没有尝试过。例如, docker export B ,然后从docker缓存中删除A和B,而 docker import B 应该仅显示一个图像。



您可以使用

  docker获取实际的父母关系图像检查< image-id> | grep -E Id | Parent 


$ b结合$ b

  docker image ls -a --digests 

检查关系。



更多信息。



构建图像时,会发生以下步骤:


  1. 构建上下文通过docker守护进程发送到主机。这基本上是Dockerfile所在目录中的所有文件。这就是为什么重要的是要使用 .dockerignore 仅发送在您的COPY文件中

  2. docker守护进程使用Dockerfile中的FROM指令创建一个临时容器。这是导入的图像,包括其自己的导入图像。然后,在该容器内执行Dockefile中的每条指令。在临时容器中进行持久更改(例如COPYing)后,它将保存其状态。这样可以有效地在最终图像上添加一层。

  3. 完成DOCKERFILE指令执行后,临时容器将被破坏。您将获得最终的图像。

您可以使用
docker history< image-id>



请注意,这提供了调试Dockerfile的便捷方法。您应该在Dockerfile中看到对应于持久性指令的层的ID。您可以使用 docker run --rm -it<图层旁边的id sh 并手动执行以下Dockerfile指令。


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.

and,

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.

and 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.

Now, questions,

  • Say I build my docker images layer by layer. A < B < C < D, etc.
  • Now if I update my docker image A, would the rest of docker images B, C, D see the changes as well, provided that the changes are not touched by them when building them? E.g., adding /etc/apt/sources.list.d/somethingnew that was never there before.
  • If I had built another set of docker images layer by layer. A < X < Y < Z, then the above changes will be reflected in X, Y, Z as well, right?
  • Now if however, the future changes to A, is made to the same file that will be changed when building B, C, D, then what would happen? For e.g., let's make it simple that docker images B, C, D each only add pkgB, pkgC, and pkgD in its layer. If I add a pkgA to A after B, C, D are build, what would happen? -- I guess there should be one single version of truth as what packages are in, for a single system, so what would it be for this case?
  • What if I'm only upgrading the packages in A? This should be OK right? Would the rest of docker images see the changes as well?

解决方案

Overall, each image contains its parent image, either as embedded bytes or as a "hard" reference to an image in your local cache if it is already there.

By "parent" I mean the FROM: someimage instruction in your Dockerfile.

I also wrote "hard" since the reference is actually a sha246 digest of the parent image. If any bit of the parent changes, the digest will be different.

There are three main cases here:

  1. You start with a clear cache (docker image ls -a shows nothing). If you docker pull ... some image from a public registry, it will have its parent embedded. A docker ps -a should show only one image.

  2. If however you already have the parent image in your cache, the docker pull ... won't download the parent again. In that case, the pulled image has a reference to the parent in your cache.

  3. If you build locally from a clear cache, docker will download the parent image and produce a child image with a reference to the parent.

It's still the same result at the end. If you replace the parent image with a newer version, the digest won't be the same.

Docker won't let you delete an image if another image references it. When you push your image to a registry, the parent is embedded (I'm skimping over caching behaviour on the registry side here). I think that you can also embed the parent by using docker export and docker import but I haven't tried it. For instance, docker export B, then delete A and B from your docker cache and docker import B should show only one image.

You can get the actual parent relationship using

docker image inspect <image-id> | grep -E "Id|Parent"

combine that with

docker image ls -a --digests

To inspect the relationships.

Some more info.

When you build an image, the following steps occur:

  1. The build context is sent to the host with the docker daemon. This is basically all the files in the directory that your Dockerfile is in. That's why it is important to make use of .dockerignore to only send files that are COPY'd in your Dockerfile.
  2. The docker daemon creates a temporary container using the FROM instruction in the Dockerfile. This is the imported image, including its own imported images. Then every instruction in the Dockefile is executed inside that container. When a persistent change is made in the temporary container (like COPY'ing), it then saves its state. This effectively adds a layer to the final image.
  3. Once finished executing the DOCKERFILE instructions, the temporary container is destroyed. You are left with the final image.

You can see all the layers in the image using docker history <image-id>

Note that this offers a handy way to debug a Dockerfile. You should see an id for the layers that correspond to persistent instructions in your Dockerfile. You can create a new container from any layer using docker run --rm -it <id next to layer> sh and manually execute the Dockerfile instructions that follow.

这篇关于了解Docker层和未来的变化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆