我可以运行 Docker 映像的中间层吗?

Posted

技术标签:

【中文标题】我可以运行 Docker 映像的中间层吗?【英文标题】:Can I run an intermediate layer of a Docker image? 【发布时间】:2017-07-24 23:18:56 【问题描述】:

当我从存储库中获取 Docker 映像时,我看到它提取了一堆带有一些 id 的层,但是当我尝试使用 docker run 运行它们时,它告诉我它不能找到它。

我可以运行 Docker 映像的某个层,我可以通过 docker history 看到,就像古生物学家在挖掘有趣的东西一样?

我尝试了什么:

docker pull ruby
Using default tag: latest
latest: Pulling from library/ruby
693502eb7dfb: Already exists
081cd4bfd521: Already exists
5d2dc01312f3: Already exists
54a5f7da9a4f: Pulling fs layer
168cf3f33330: Pulling fs layer
021d84fef638: Pulling fs layer
168c3c107cd1: Waiting
f001b782a027: Waiting

然后:

docker run --rm -it 5d2dc01312f3 bash
Unable to find image '5d2dc01312f3:latest' locally

当我提取已构建并发布的图像时,我突然想到了这个问题。我可以清楚地看到一层有将近 1.2 GB 的大小。这是我从用于构建映像的机器上复制一些文件的层,在下一层我清理并删除了一些文件,因为我正在清理映像,但映像的总大小约为 1.5 GB,意味着存在 1.2 GB 的大脂肪层。我就是想看看能不能看到那层脂肪。

【问题讨论】:

大胖文件肯定在那里,因为它是在一个层中添加的(dockerfile命令)并在另一个层中删除。 Docker 不支持在同一层运行多个命令,但它们有一个实验性的build --squash 选项来压缩镜像层。见docs.docker.com/engine/reference/commandline/build/… 我认为这是一项新功能,可以将 fs 层压缩为一个,从而减小整个图像的大小 【参考方案1】:

您可以运行 Docker 层的中间映像,这可能就是您想要的。

在构建过程中,您可能需要在构建过程中的某个点(步骤)检查图像,例如在您的 Docker 构建输出中,您会看到:

Step 17/30 : RUN rm -rf /some/directory
---> Running in 5ab963f2b48d

5ab963f2b48d 是图像 ID,当您列出图像时,您会在列表中看到该 ID,例如

$ docker image ls --all
REPOSITORY    TAG      IMAGE ID       CREATED        SIZE
<none>        <none>   5ab963f2b48d   7 minutes ago  1.18GB

例如,要运行该图像(使用终端),您可以简单地:

docker run -i -t 5ab963f2b48d /bin/bash

另见:Run a Docker Image as a Container

【讨论】:

我认为这仅在您构建映像的 buid 机器中是可能的,但是您从 docker hub registery 获取的 docker 映像怎么样 对我来说,docker build 命令在我可以docker run 之前删除了图层,所以它只是抱怨找不到图像 ID。【参考方案2】:

不,您不能运行图层。你只能运行一个图像。所以这取决于是否存在与该层关联的中间图像!

这是一个典型的场景:

    您在主机上构建映像: 中间映像将是 为此层创建(这是为 docker build cache 完成的) 将图像推送到注册表:仅推送最终图像(引用所有层),但不推送任何中间图像。 您将映像拉到另一台主机上: 最终映像(包含所有层)现在可以在另一台 Docker 主机上使用。您可以通过运行docker history &lt;image-id&gt; 来显示其层

拉取图像时看到的摘要是层的摘要,它们不是中间图像。

docker history 输出的图像列中的值&lt;missing&gt; 表示没有与这些层关联的图像。因此,真的没有什么可运行的。

Docker 守护进程将不允许访问这些层,除非映像是在同一 docker 主机(或 Docker cache was distributed)上构建的。

您可以在explaining-docker-image-ids 阅读有关层的更多信息。

【讨论】:

我了解您,如果图像被推送到注册表并拉入其他主机,则中间图像将无法在其他主机中访问,但我的问题是是否可以访问一些中间层发布了 docker 图像,我认为这是可能的,因为这就是 docker 的工作方式,我只是想知道是否有办法手动完成,你觉得我 我认为我们需要一个 docker 黑客来解决问题 @achabahe 我不确定我理解您所说的“已发布的 docker 映像”是什么意思。您的意思是如果没有与该图层关联的图像,则访问该图层? 最终的 docker 镜像,例如在 dockerhub 等某个注册表中发布 好的。我将尝试更深入地挖掘以 100% 确定何时有时间,但我的直觉是 docker 守护程序永远不会允许您创建图层的图像(然后可能会运行它),或者手动操作图层的图像。从安全的角度来看,这将是危险的。【参考方案3】:

是的,这是可能的,但如果您使用的是 Docker 1.10 或更高版本,则只能使用自构建映像。例如,docker history ruby 将为除最顶层之外的所有层输出 &lt;missing&gt;,因为它们没有标签。

如果你自己构建它,它们会有一个标签,你可以像往常一样启动它们。

【讨论】:

我知道这种可能性,当进行本地构建时,中间层将在本地缓存,但是如果我从 repo 获取 docker 映像,我确信在一层中有一些文件在下一层被删除。是不是可以只运行那个特定的层和以前的层并获取那些资源,我会更新我的问题 我确定这可以通过创建一些元数据来实现,但我不知道具体如何 是的,我认为可能是因为文件系统层在那边

以上是关于我可以运行 Docker 映像的中间层吗?的主要内容,如果未能解决你的问题,请参考以下文章

Docker - 无法连接到正在运行的映像

CentOS Docker 映像的目的是啥? [复制]

我可以控制 Docker 映像中绑定安装卷的所有者吗?

如何在 Azure 上安装元数据库 docker 映像

是啥触发 Elastic Beanstalk 拉入更新的 Docker 映像

apache 特定的 cron-jobs 不应该在 docker 映像中运行吗?