使用 docker 是否有办法确定哪些图像依赖于另一个图像

使用 docker 是否有办法确定哪些图像依赖于另一个图像

通过docker它可以识别所有命名和标记的容器并将docker images它们列出。

我可以找出给定图像所依赖的其他图像docker inspect --format '{{.RootFS.Layers}}' _imageId_,并且通过手动比较 SHA,我可以看到图像 B 使用了图像 A。

有什么方法可以让docker告诉我或者使用bash(或便携式shell)脚本来查找依赖于给定图像的所有命名图像。例如,在这个例子中,当我搜索依赖于A的图像时会返回B。

我一直在搜索 docker 帮助输出、在线 docker 文档、google 和 SE、SO、SU 搜索,试图找到一种现有的替代方法来手动发现依赖关系,但都没有成功。

答案1

正如问题所述,似乎没有内置方法可以做到这一点。以下docker-find-dependants 脚本在此处维护并完成工作

#!/bin/bash

# Script to determine what named images and containers are dependent on the specified image (or a containers image) from stdin or in the args
# An unmatchable input is ignored
# All of the following will be found:
#    Any image name / tag / name:tag / id that has a prefix in it that matches the input
#    Any other image that relies on the images specified
#    Any containers (running or not) that use any of these images

set -euf -o pipefail

debugMsg() {
    true
    #printf "%s\n" "$@" >&2
}


specifiedParents=""
# Find all the images that need to be removed
if [ "$#" -ge "1" ]; then
    # Images for removal in args
    specifiedParents="$(printf " %s\n" "$@")"
else
    # Images for removal to arrive via stdin
    while IFS= read -r inStr; do
        if [ -n "$inStr" ]; then
            specifiedParents="$(printf "%s %s\n" "$specifiedParents" "$inStr")"
        fi
    done
fi
debugMsg "DBG:1 specifiedParents = '$specifiedParents'"

# Check there is some input
if [ -z "$specifiedParents" ]; then
    printf "%s" "Nothing specified to search for; images/containers must be specified as either args or on the stdin" >&2 
    exit 1
fi

# Collect the container and image info
containersData="$(docker ps -a --format 'Container {{.ID}} {{.Image}} {{.Names}} {{.Labels}}' --no-trunc)"
allImagesData="$(docker images -a --format 'Image {{.ID}} {{.Repository}}:{{.Tag}} {{.Repository}} {{.Tag}}' --no-trunc | sed 's/ [^:]*:/ /')"
namedImagesData="$(docker images --format 'Image {{.ID}} {{.Repository}}:{{.Tag}}' --no-trunc | sed 's/ [^:]*:/ /')"
debugMsg "DBG:2 containersData = '$containersData'"
debugMsg "DBG:3 allImagesData = '$allImagesData'"
debugMsg "DBG:4 namedImagesData = '$namedImagesData'"

# Check to see if you can find a matching container
parents=""
while IFS= read -r aParent; do
    if [ -z "$aParent" ]; then
        continue
    fi

    # Use space to ensure matching starts at the beginning of a field
    anImageId=" $(printf "%s" "$containersData" | grep -F " $aParent" | awk '{print $3}' || true)"
    if [ "$anImageId" != " " ]; then
        # A container matched so use the image ID
        parents="$(printf "%s%s\n" "$parents" " $anImageId")"
    else
        # Not a container, so presumably an image
        parents="$(printf "%s%s\n" "$parents" " $aParent")"
    fi
done <<< $(printf "%s\n" "$specifiedParents") # Performing while inside this shell
#debugMsg "DBG:5 parents = '$parents'"

# Get the full parent image ID's
parentImageIds=""
while IFS= read -r aParent; do
    debugMsg "DBG:6 aParent = '$aParent'"
    # Find anything matching the parent and get it's full ID
    while IFS= read -r parentImageId; do
        if [ -z "$parentImageId" ]; then
            continue
        fi
        debugMsg "DBG:7 parentImageId = '$parentImageId'"
        # Add the full ID to the parentImageIds, including a space to assist matching later
        parentImageIds="$(printf "%s%s\n" "$parentImageIds" " $parentImageId")"
    done <<< $(printf "%s" "$allImagesData" | grep -F " $aParent" | awk '{print $2}')
done <<< $(printf "%s" "$parents") # Performing while inside this shell
debugMsg "DBG:8 parentImageIds = '$parentImageIds'"

# Stop if there are no parents
if [ -z "$parentImageIds" ]; then
    exit 0
fi

# Deduplicate
parentImageIds="$(printf "%s" "$parentImageIds" | LC_ALL=C sort -u)"
debugMsg "DBG:9 parentImageIds = '$parentImageIds'"

# Find descendent images
descendentImages=""
while IFS= read -r imageData; do
    anImageId="$(printf "%s" "$imageData" | awk '{print $2}')"

    # Check to see if this ID is a descendent of parentImageIds by imageInfo by moving through it's lineage
    areDescendents=""
    imageIdsChecked=""
    while true; do
        # Record that anImageId is being checked; including the space at the start to assist matching later
        imageIdsChecked="$(printf "%s%s\n" "$imageIdsChecked" " $anImageId")"

        if printf "%s" "$descendentImages" | grep -q -F "$anImageId"; then
            # Already determined that anImageId is a descendent of parentImageIds so TheImage is too
            areDescendents="true"
            break;
        else
            if printf "%s" "$parentImageIds" | grep -q -F " $anImageId"; then
                # TheImage is a descendent of parentImageIds
                areDescendents="true"
                break;
            fi

            # Move onto the parent of anImageId
            anImageId="$(docker inspect --format '{{.Parent}}' "$anImageId" | sed 's/.*://')"
            if [ -z "$anImageId" ]; then
                # Reached the end of the line; abandon all hope ye who enter here
                break;
            fi
        fi
    done

    # Add descendents to the descendentImages
    if [ -n "$areDescendents" ]; then
        descendentImages="$(printf "%s%s\n" "$descendentImages" "$imageIdsChecked")"
    fi
done <<< $(printf "%s" "$allImagesData") # Performing while inside this shell
debugMsg "DBG:10 descendentImages = '$descendentImages'"

checkIfDescendentImageFound() {
    # Check to see if this is a descendent from any parent
    # $1 is thisImageId
    # $2 is the display text
    # Using the space to ensure matching form the start of an ID
    if printf "%s" "$descendentImages" | grep -q -F " $1"; then
        # We've found a descendent; display it quick before it gets away
        debugMsg "DBG: Found "
        printf "%s\n" "$2"
    fi
}

# Identify any named images that are descendents of the parentImageIds
debugMsg "DBG:11 namedImagesData = '$namedImagesData'"
printf "%s\n" "$namedImagesData" | while IFS= read -r imageData; do
    thisImageId="$(printf "%s" "$imageData" | awk '{print $2}')"
    checkIfDescendentImageFound "$thisImageId" "$imageData"
done

# Identify containers that rely on images that are descendents of the parentImageIds
debugMsg "DBG:12 containersData = '$containersData'"
printf "%s\n" "$containersData" | while IFS= read -r containerData; do
    thisImageId="$(printf "%s" "$containerData" | awk '{print $3}')"
    checkIfDescendentImageFound "$thisImageId" "$containerData"
done

例子:

$ docker ps
CONTAINER ID        IMAGE               COMMAND                 CREATED             STATUS              PORTS               NAMES
f89b835ae7a0        96c117cf0a5e        "/bin/sleep infinity"   12 hours ago        Up 12 hours                             test
$ docker images -a
REPOSITORY          TAG                   IMAGE ID            CREATED             SIZE
golang-build        2017-03-09T05-46GMT   96c117cf0a5e        39 hours ago        293 MB
<none>              <none>                752877a5f5b1        39 hours ago        293 MB
<none>              <none>                cb1c86494369        39 hours ago        3.98 MB
alpine              latest                4a415e366388        7 days ago          3.98 MB
$ docker-find-dependants blah
$ docker-find-dependants 752877a5f5b1
Image 96c117cf0a5ef75c6203f862ec92ae75418c1a431d86440dd71b945e5fdbff77 golang-build:2017-03-09T05-46GMT
Container f89b835ae7a08e0394c080d0e57de2020f6a9c6dd334bc078913171d4171962f 96c117cf0a5e test 

答案2

不是一个狂欢解决方案 - 但对于那些最终来到这里只是想快速了解依赖关系的人来说民众图像 -包含.dev非常适合直观地探索这些信息(图像层次结构、图层、文件等)。

例如 - 查看continuumio/miniconda3:4.10.3p0图像,我很快就能看出它依赖于debian:buster-20210721-slim图像。

相关内容