我有一个Docker图像,我想找出它是从哪个图像创建的。当然有多个层,但我想找出最后一个图像(在docker文件中的FROM语句为这个图像)?
我尝试使用docker image history
和docker image inspect
,但在那里找不到此信息。
我尝试使用以下命令,但它显示错误消息
alias dfimage="sudo docker run -v /var/run/docker.sock:/var/run/docker.sock --rm xyz/mm:9e945ff"
dfimage febae8978318
这是我收到的错误消息
container_linux.go:235: starting container process caused "exec: \"febae8978318\": executable file not found in $PATH"
/usr/bin/docker-current: Error response from daemon: oci runtime error: container_linux.go:235: starting container process caused "exec: \"febae8978318\": executable file not found in $PATH".
4条答案
按热度按时间rekjcdws1#
简单的方法是使用
上面的命令将给予如下输出
然后查看IMAGE列,获取刚好位于第一个
<missing>
上方的映像IDa24bb4013296
那就做
对于Linux
适用于Windows
这将为您提供基础映像名称
50few1ms2#
这些信息实际上并不存在,一个图像包含其父级的图层,但是没有一种简单的方法可以将图层摘要反向转换回
FROM
语句,除非你碰巧有(或者能够找出)包含这些图层的图像。如果您手头有父图像(或可以找到它们),则可以通过交叉引用层来推断图像用于其FROM语句(或祖先)的图像。
理论示例
假设您的图像
FOO
包含层1 2 3 4 5 6
,如果您的系统上有另一个图像BAR
包含层1 2 3
,则可以推断图像BAR
是图像FOO
的祖先--即FROM BAR
可能在其层次结构中的 * 某个点 * 使用过。进一步假设您有另一个图像
BAZ
,其中包含层1 2 3 4 5
,您可以推断图像BAZ
在其祖先中具有图像BAR
,并且图像FOO
继承自图像BAZ
(因此间接继承自BAR
)。由此,您可以推断出这些图像的停靠文件的信息可能如下所示:
您可以通过查看每个映像的
docker image history
来获得确切的命令。然而,这里要记住的一件重要事情是,Docker标记是可变的;维护人员会创建新的映像并将标签移动到这些映像上。因此,如果您今天使用
FROM python:3.8.1
创建了一个映像,它将不会包含与几周前使用相同的FROM
行创建的映像相同的层。您需要SHA256摘要来确保您使用的是 * 完全 * 相同的映像。实际示例,本地映像
现在我们已经了解了识别图像及其基础的理论,下面让我们通过一个真实的示例将其付诸实践。
注:因为我使用的标签会随着时间的推移而变化(见上文RE:标签可变性),我将使用SHA256摘要来提取本例中的图像,以便此答案的查看者可以重现这些图像。
假设我们有一个特定的图像,我们想找到它的基础,我们将在这里使用官方的
maven
图像。首先,我们来看看它的层次。
这将输出层:
现在,我们可以尝试找到其他拥有这些图层的(严格)子集的图像。假设您手头有这些图像,您可以通过交叉引用磁盘上的图像图层来找到它们,例如,使用
docker image inspect
。在这种情况下,我只是碰巧知道这些图像是什么,并有他们的手(我会在后面讨论你可能会做什么,如果你没有手头上的图像),所以我们将继续拉这些图像,看看层。
如果您想继续操作:
如果我们检查这些图像,并将它们与
docker image inspect
输出的maven
图像中的图层进行比较,我们可以确认openjdk
和debian
中的图层存在于原始maven
图像中。如上所述,由于这5层是maven映像中8层的严格子集,因此我们可以得出结论,
openjdk
和debian
映像至少都在maven
映像的祖先路径中。我们可以进一步推断,最后3层最有可能来自
maven
图像本身(或者,可能是某个未知图像)。警告,当您本地没有图像时
当然,以上方法之所以有效,是因为我手头正好有所有的图片,所以,你要么需要图片,要么可以通过图层摘要找到它们。
您仍然可以使用Docker Hub等注册中心或您自己的私人存储库中提供的信息来解决这个问题。
对于官方图像,docker-library/repo-info包含官方图像的历史信息,包括过去几年中编目的各种标签的层摘要。例如,您可以将其用作层信息源。
如果你能把它想象成一个图层摘要的数据库,你至少可以推断出这些官方图片的祖先。
"分发"(远程)摘要与"内容"(本地)摘要
需要注意的一个重要警告是,当你在本地检查一个图像的层摘要时,你得到的是层的 * 内容 * 摘要。如果你在注册表清单中查看层摘要(就像docker-library/repo-info项目中出现的),你得到的是压缩的 * 分发 * 摘要,并且不能将层摘要与内容进行比较。
因此,您只能比较摘要
local <--> local
或remote <--> remote
。示例,使用远程映像
假设我想做同样的事情,但是我想关联远程存储库中的图像并找到它的基,我们可以通过查看远程清单中的层来做同样的事情。
您可以找到如何针对特定注册表执行此操作的参考,如this answer for dockerhub中所述。
使用上例中的相同图像,我们会发现 * distribution * 层摘要也以相同的方式匹配。
关于仓库中的分发摘要的另一个警告是,你只能比较相同manifest schema version的摘要,所以,如果一个映像是用manifest v1推送的,那么它不会用manifest v2再次推送相同的摘要。
TL; DR
图像包含其祖先图像的层。因此,如果图像A包含图像B层的严格子集,则您知道图像B是图像A的后代。
您可以使用Docker图像的此属性来确定从中派生图像的基础图像。
twh00eeo3#
您可以使用此答案中建议的方法:https://stackoverflow.com/a/53841690/3691891
首先,拉动
chenzj/dfimage
:获取映像的ID:
将
<IMAGE_NAME>
替换为映像的名称。使用此ID作为chenzj/dfimage
的参数:如果您觉得这太难,只需提取
chenzj/dfimage
映像,然后使用以下docker-get-dockerfile.sh
脚本:您需要将图像名称作为参数传递。示例用法:
s3fp2yjn4#
用上面的命令从那个图像运行一个docker容器(用你的图像名称和标签改变“image:tag”)。你的容器将打印你需要回答你的问题的细节。