繁体   English   中英

如何找出 docker 图像的基础图像

[英]How to find out the base image for a docker image

我有一个 docker 图像,我想知道它是从哪个图像创建的。 当然有多层,但我想找出最后一张图片(这张图片的dockerfile中的FROM语句)?

我尝试使用docker image historydocker 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".

简单的方法是使用

docker image history deno

上面的命令会给你 output 像这样

在此处输入图像描述

然后只需查看 IMAGE 列并获取位于第一个<missing>上方的a24bb4013296的图像 ID

然后做

对于 Linux

docker image ls | grep a24bb4013296

适用于 Windows

docker image ls | findstr a24bb4013296

这将为您提供基本图像名称

在此处输入图像描述

您可以使用此答案中建议的方法: https://stackoverflow.com/a/53841690/3691891

首先,拉chenzj/dfimage

docker pull chenzj/dfimage

获取图像的 ID:

docker images | grep <IMAGE_NAME> | awk '{print $3}'

<IMAGE_NAME>替换为您的图像名称。 将此 ID 用作chenzj/dfimage的参数:

docker run -v /var/run/docker.sock:/var/run/docker.sock --rm chenzj/dfimage <IMAGE_ID>

如果您觉得这太难了,只需拉取chenzj/dfimage图像,然后使用以下docker-get-dockerfile.sh脚本:

#!/usr/bin/env sh

if [ "$#" -lt 1 ]
then
    printf "Image name needed\n" >&2
    exit 1
fi

image_id="$(docker images | grep "^$1 " | awk '{print $3}')"
if [ -z "$image_id" ]
then
    printf "Image not found\n" >&2
    exit 2
fi

docker run -v /var/run/docker.sock:/var/run/docker.sock --rm chenzj/dfimage "$image_id"

您需要将图像名称作为参数传递。 示例用法:

$ ./docker-get-dockerfile.sh alpine
FROM alpine:latest
ADD file:fe64057fbb83dccb960efabbf1cd8777920ef279a7fa8dbca0a8801c651bdf7c in /
CMD ["/bin/sh"]

确切地说,这些信息并不真正存在。 图像将包含其父级的层,但没有简单的方法将层摘要反转回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并且图像A继承自图像BAZ (因此间接继承自BAR )。

由此,您可以推断出这些图像的 dockerfile 的信息可能看起来像这样:

# Dockerfile of image BAR
FROM scratch
# layers 1 2 and 3
COPY ./one /
COPY ./two /
COPY ./three /
# Dockerfile of Image BAZ
FROM BAR
RUN echo "this makes layer 4" > /four
RUN echo "this makes layer 5" > /five
# Dockerfile of image FOO
FROM BAZ
RUN echo "this makes layer 6" > /six

您可以通过查看每个图像的docker image history来获得确切的命令。

然而,这里要记住的一件重要事情是 docker 标签是可变的; 维护人员制作新图像并将标签移动到这些图像。 因此,如果您今天使用FROM python:3.8.1构建了一个映像,那么它不会包含与几周前使用相同FROM行构建的映像相同的层。 您需要 SHA256 摘要以确保您使用的是完全相同的图像。

实际示例,本地图像

现在我们了解了识别图像及其基础背后的理论,让我们用一个真实的例子来实践它。

注意:因为我使用的标签会随着时间而改变(参见上面的 RE:标签可变性),我将使用 SHA256 摘要来提取此示例中的图像,以便此答案的查看者可以复制它。

假设我们有一个特定的图像,我们想找到它的基础。 我们将在这里使用官方的maven图像。

首先,我们来看看它的层次。

# maven:3.6-jdk-11-slim at time of writing, on my platform
IMAGE="docker.io/maven@sha256:55f1c145a04e01706233d68fe0b6b20bf76f765ab32f3fe6e29c8ef933917af6"
docker pull $IMAGE
docker image inspect $IMAGE | jq -r '.[].RootFS.Layers[]'

这将 output 层:

sha256:6e06900bc10223217b4c78081a857866f674c462e4f90593b01894da56df336d
sha256:eda2f4da9b1e70500ac340d40ee039ef3877e8be13b9a24cd345406bf6693412
sha256:6bdb7b3c3e226bdfaa911ba72a95fca13c3979cd150061d570cf569e93037ce6
sha256:ce217e530345060ca0973807a3288560e1e15cf1a4eeec44d6aa594a926c92dc
sha256:f256c980a7d17a00f57fd42a19f6323fcc2341fa46eba128def04824cafa5afa
sha256:446b1af848de2dcb92bbd229ca6ecaabf2f48dab323c19f90d02622e09a8fa67
sha256:10652cf89eaeb5b5d8e0875a6b1867b5cf92c509a9555d3f57d87fab605115a3
sha256:d9a4cf86bf01eb170242ca3b0ce456159fd3fddc9c4d4256208a9d19bae096ca

现在,从这里,我们可以尝试找到具有这些层的(严格)子集的其他图像。 假设您手头图像,您可以通过交叉引用磁盘上的图像层来找到它们,例如,使用docker image inspect

在这种情况下,我只是碰巧知道这些图像是什么并且手头有它们(我稍后会讨论如果你手头没有图像你可能会做什么)所以我们将 go 提前并拉出那些图像并查看图层。

如果你想跟随:

# openjdk:11.0.10-jdk-slim at time of writing, on my platform
OPENJDK='docker.io/openjdk@sha256:fe6a46a26ff7d6c31b258e07b3d53f0c42fe68f55f646cc39d60d0b17cbc827b'

# debian:buster-20210329-slim at time of writing on my platform
DEBIAN='docker.io/debian@sha256:088be7d6017ad3ae98325f47707112e1f61687c371be1865e55d5e5531ca97fd'

docker pull $OPENJDK
docker pull $DEBIAN

If we inspect these images and compare them against the layers we saw in the output of docker image inspect for the maven image, we can confirm that the layers from openjdk and debian are present in our original maven image.

$ docker image inspect $DEBIAN | jq -r '.[].RootFS.Layers[]'
sha256:6e06900bc10223217b4c78081a857866f674c462e4f90593b01894da56df336d

$ docker image inspect $OPENJDK | jq -r '.[].RootFS.Layers[]'
sha256:6e06900bc10223217b4c78081a857866f674c462e4f90593b01894da56df336d
sha256:eda2f4da9b1e70500ac340d40ee039ef3877e8be13b9a24cd345406bf6693412
sha256:6bdb7b3c3e226bdfaa911ba72a95fca13c3979cd150061d570cf569e93037ce6
sha256:ce217e530345060ca0973807a3288560e1e15cf1a4eeec44d6aa594a926c92dc

如前所述,因为这 5 层是 maven 图像中 8 层的严格子集,我们可以得出结论, openjdkdebian图像至少都在maven图像的祖先路径中。

我们可以进一步推断,最后 3 层最有可能来自maven图像本身(或者,可能是一些未知图像)。

警告,当您在本地没有图像时

现在,当然上述方法只适用,因为我碰巧手头有所有图像。 因此,您要么需要图像,要么能够通过图层摘要找到它们。

您仍然可以使用 Docker Hub 或您自己的私有存储库等注册中心提供的信息来解决这个问题。

对于官方图像, docker-library/repo-info包含有关官方图像的历史信息,包括过去几年编目的各种标签的层摘要。 例如,您可以将其用作图层信息的来源。

如果你能把它想象成一个层摘要的数据库,你至少可以推断出这些官方图像的祖先。

“分发”(远程)摘要与“内容”(本地)摘要

需要注意的一个重要警告是,当您在本地检查图像的图层摘要时,您将获得图层的内容摘要。 如果您正在查看注册表清单中的层摘要(如 docker-library/repo-info 项目中出现的内容),您将获得压缩的分发摘要,并且无法将层摘要与内容进行比较。

因此,您可以仅比较摘要local <--> localremote <--> remote

示例,使用远程图像

假设我想做同样的事情,但我想在远程存储库中关联图像并找到它的基础。 我们可以通过查看远程清单中的层来做同样的事情。

您可以找到参考如何为您的特定注册表执行此操作,例如 dockerhub https://stackoverflow.com/a/57878742/5747944此处

使用上面示例中的相同图像,我们会发现分布层摘要也以相同的方式匹配。

$ get-remote-layers $IMAGE
sha256:6fcf2156bc23db75595b822b865fbc962ed6f4521dec8cae509e66742a6a5ad3
sha256:96fde6667c188c81fcddee021ccbb3e054ebe83350fd4609e17a3d37f0ec7f9d
sha256:74d17759dd2a1b51afc740fadd96f655260689a2087308e40d1865a0098c5fae
sha256:bbe8ebb5d0a64d265558901c7c6c66e1d09f664da57cdb2e5f69ba52a7109d31
sha256:b2edaadd7dd62cfe7f551b902244ee67b84bc5c0b6538b9480ac9ca97a0a4986
sha256:0fca65d33e353bdfdd5edd8d4c8ab5efde52c078bd25e2dcf454f995e5420725
sha256:d6d771d0512387eee1e419a965b929a9a3b0365cf1935b3719d60bf9feffcf63
sha256:dee8cd26669373102db07820072127c46bbfdad340a586ee9dfe60ae933eac2b

$ get-remote-layers $DEBIAN
sha256:6fcf2156bc23db75595b822b865fbc962ed6f4521dec8cae509e66742a6a5ad3

$ get-remote-layers $OPENJDK
sha256:6fcf2156bc23db75595b822b865fbc962ed6f4521dec8cae509e66742a6a5ad3
sha256:96fde6667c188c81fcddee021ccbb3e054ebe83350fd4609e17a3d37f0ec7f9d
sha256:74d17759dd2a1b51afc740fadd96f655260689a2087308e40d1865a0098c5fae
sha256:bbe8ebb5d0a64d265558901c7c6c66e1d09f664da57cdb2e5f69ba52a7109d31
docker run image:tag cat /etc/*release*

使用上面的命令从该镜像运行一个 docker 容器(将“image:tag”更改为您的镜像名称和标签)。 您的容器将打印您需要回答问题的详细信息。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM