如问题中所述,似乎没有内置的方法可以做到这一点。以下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