bash 如何查找正在运行的 Docker 容器的所有图像标签?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/56646899/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 17:08:13  来源:igfitidea点击:

How to find all image tags of a running Docker container?

linuxbashdockerdocker-containerdocker-image

提问by Forivin

I have a bunch of Docker containers running on a server and I used the "latest" tag or no tag at all for all of them. Now I want to freeze the image versions, but I have no idea when I pulled these images, so I can't tell which version "latest" is referring to. docker psis just showing me that the containers use the "latest" or no tag, like this:

我有一堆 Docker 容器在服务器上运行,我对所有容器都使用了“最新”标签或根本不使用标签。现在我想冻结图像版本,但我不知道何时提取这些图像,所以我无法分辨“最新”指的是哪个版本。docker ps只是向我展示容器使用“最新”或不使用标签,如下所示:

# docker ps
CONTAINER ID        IMAGE                  COMMAND                  CREATED             STATUS              PORTS               NAMES
371d6675888b        node:latest            "npm start"              6 days ago          Up 2 hours                              project_xyz_1
ca5a75425a34        selenium/node-chrome   "/usr/bin/nohup go..."   6 days ago          Up 2 hours                              project_xyz-chrome_1
...

All images that I use are public images from the docker hub.

我使用的所有图像都是来自 docker hub 的公共图像。

I thought maybe I could use the hex ID that docker ps shows for all the containers, but then I realized that the IDs are container IDs and not image IDs.

我想也许我可以使用 docker ps 为所有容器显示的十六进制 ID,但后来我意识到 ID 是容器 ID 而不是图像 ID。

Is it maybe possible to get the image IDs/hashes of all running containers and then scan for all matching tags or something like that?

是否有可能获取所有正在运行的容器的图像 ID/哈希,然后扫描所有匹配的标签或类似的东西?

Docker version: 18.09.1, build 4c52b90

Docker 版本:18.09.1,构建 4c52b90

Edit:

编辑:

So there have been some answers showing how to get the IDs (digests) of the images, but I need to somehow find the actual tags of those images. After doing some research, I found that the docker hub has an API and that there is a way to get all tags for a given image and there is a way to get the digest for a given image+tag. After looking at the API and a lot of examples from stackoverflow, I came up with this: (It also includes the code required to get the digest of local images, taken form the answers below)

所以已经有一些答案显示了如何获取图像的 ID(摘要),但我需要以某种方式找到这些图像的实际标签。在做了一些研究之后,我发现 docker hub 有一个 API,并且有一种方法可以获取给定图像的所有标签,并且有一种方法可以获取给定图像 + 标签的摘要。在查看了 API 和来自 stackoverflow 的大量示例后,我想出了这个:(它还包括获取本地图像摘要所需的代码,取自以下答案)

function getDigestByImageNameWithTag () {
    TARGET_IMAGE_NAME_WITH_TAG="" # works with and without tag
    docker image inspect --format '{{index .RepoDigests 0}}' "$TARGET_IMAGE_NAME_WITH_TAG" | cut -d '@' -f2
}

function getTagsByDigest () {
    TARGET_IMAGE_NAME=""
    TARGET_DIGEST=""

    # prepend the image name with "library/" if it doesn't contain a slash
    if [[ $TARGET_IMAGE_NAME != *"/"* ]]; then
        TARGET_IMAGE_NAME="library/$TARGET_IMAGE_NAME"
    fi

    # get authorization token for the given image name
    TOKEN=$(curl -s "https://auth.docker.io/token?service=registry.docker.io&scope=repository:$TARGET_IMAGE_NAME:pull" | jq -r .token)

    # find all tags for the given image name
    ALL_TAGS=$(curl -s -H "Authorization: Bearer $TOKEN" https://index.docker.io/v2/$TARGET_IMAGE_NAME/tags/list | jq -r .tags[])

    # itate over all these tags
    for TAG in ${ALL_TAGS[@]}; do
        # get image digest
        DIGEST=$(curl -s -D - -H "Authorization: Bearer $TOKEN" -H "Accept: application/vnd.docker.distribution.manifest.v2+json" https://index.docker.io/v2/$TARGET_IMAGE_NAME/manifests/$TAG | grep Docker-Content-Digest | cut -d ' ' -f 2)
        # if the tag matches the given digest
        if [[ $TARGET_DIGEST = $DIGEST ]]; then
            # "return" the tag
            echo "$TAG"
        fi
    done
}

function getContainerImageNames () {
    docker inspect $(docker ps  | awk '{print }' | grep -v ID) | jq .[].RepoTags | grep -v "\[" | grep -v "\]" | grep " " | cut -d '"' -f2 | cut -d '/' -f2-
}


# get all image names of all local containers
IMGS_WITH_TAG=$(getContainerImageNames)
# iterate of those image names
for IMAGE_NAME_WITH_TAG in ${IMGS_WITH_TAG[@]}; do
    # get the digest of the current iteration's IMAGE_NAME_WITH_TAG
    DIGEST=$(getDigestByImageNameWithTag $IMAGE_NAME_WITH_TAG)
    echo "TARGET_DIGEST: $DIGEST" 
    # get the raw image name without the tag
    IMAGE_NAME=$(echo "$IMAGE_NAME_WITH_TAG" | cut -d ':' -f1)
    # find all tags for this image that have the same digest
    MATCHING_TAGS=$(getTagsByDigest $IMAGE_NAME $DIGEST)
    echo "Image: $IMAGE_NAME_WITH_TAG"
    echo "Image digest: $IMAGE_NAME"
    echo "Image tags with same digest: "
    echo "$MATCHING_TAGS"
    echo "-----------------------------"
done

Unfortunately it seems to take forever to finish. I'm not sure if I'm doing something wrong, but that's the best thing I could come up with.

不幸的是,它似乎需要很长时间才能完成。我不确定我是否做错了什么,但这是我能想到的最好的办法。

Any ideas on how to make this work properly?

关于如何使其正常工作的任何想法?

回答by Adiii

I think this is a better approach without inspecting the container, as docker ps already printing the docker image tag form which the container is created.

我认为这是一种无需检查容器的更好方法,因为 docker ps 已经打印了创建容器的 docker 图像标签表单。

docker inspect $(docker ps  | awk '{print }' | grep -v ID) | jq .[].RepoTags

So first this gets the list of running containers, then inspect each image being used by running container and using jqget all repo tags of that image.

因此,首先获取正在运行的容器列表,然后检查正在运行的容器正在使用的每个映像并使用jq获取该映像的所有 repo 标签。

Here is the output.

这是输出。

docker images tags and name

docker 图像标签和名称

Updated:

更新:

Here is you go using skopeo, you can do using API but will do the effort, so why if you have skopeo

这是你去使用skopeo,你可以使用 API 但会努力,所以为什么如果你有 skopeo

You do not need to install skopeoyou can run the container and then or remove once get the result, or you can install, script support both

你不需要安装skopeo你可以运行容器然后或删除一次得到结果,或者你可以安装,脚本支持两者

running_container=$(docker ps  | awk '{print }' | grep -v ID) 
echo "running container: $running_container"
for image in $running_container
do
local_tag=$(echo "$image" | awk -F":" '{print }')
if [ -z $local_tag ]; then
# if tag is empty then tag is latest
local_tag="latest"
image="$image":"$local_tag"
fi
local_digest=$(docker inspect $image | jq '.[].RepoDigests[]' | awk -F"@" '{print }' | tr -d '"')
echo "Local digest is:" $local_digest
remote_digest=$(docker run --rm --env image=$image alexeiled/skopeo:latest ash -c "skopeo inspect docker://docker.io/$image" | jq '.Digest' | tr -d '"' )
echo $remote_digest 

# option2 install the skopeo on your local system
# remote_digest=$(skopeo inspect docker://docker.io/$image | jq '.Digest' | tr -d '"')
echo "Remote digest is : "$remote_digest

if [ "${local_digest}" == "${remote_digest}" ]; then
echo "local image is up to date with remote"
else
echo "Remote image is updated; please run docker pull $image"
fi
done

enter image description here

在此处输入图片说明

回答by BMitch

The RepoDigest field in the image inspect will have a sha256 reference if you pulled the image from a registry:

如果您从注册表中提取图像,图像检查中的 RepoDigest 字段将具有 sha256 引用:

docker ps --format '{{.Image}}' | xargs \
  docker image inspect --format '{{if .RepoDigests}}{{index .RepoDigests 0}}{{end}}'

For a single image like node:lateston your host, that looks like:

对于像node:latest主机上的单个图像,它看起来像:

docker image inspect --format '{{index .RepoDigests 0}}' node:latest

That digest cannot be changed by a push to the registry of the same tag name. When you pull the updated tag from the registry, you will see this digest update.

该摘要不能通过推送到相同标签名称的注册表来更改。当您从注册表中提取更新的标记时,您将看到此摘要更新。

回答by Danish Faizan

The docker inspect command can be used for this. You can take a look at the answer here https://stackoverflow.com/a/54075889/8113039

docker inspect 命令可用于此目的。你可以看看这里的答案https://stackoverflow.com/a/54075889/8113039

回答by Guillaume Barré

Docker images and containers are identified by an ID and for a running container you can get the Id of its image and then pull the image corresponding to the given ID.

Docker 镜像和容器由 ID 标识,对于正在运行的容器,您可以获取其镜像的 ID,然后拉取与给定 ID 对应的镜像。

First you need to use docker inspecton all your running containers in order to get the sha256Id the image on which the container is based.

首先,您需要docker inspect在所有正在运行的容器上使用,以获取sha256容器所基于的映像的Id。

docker inspectreturns the image ID under "Image":

docker inspect返回下的图像 ID "Image"

{
  "Id": "6de053a2afa4499471c5e5c2afe0b0d83c9c7e50fc7e687fb63a7ebfd2bff320",
  ...
  },
  "Image": "sha256:26eb6780e26887a6838684a549562c0404fd85c55f71e0af6c79a4da5505d2a7",
  ....
}

Then you simply have to pull those images by digest (immutable identifier)

然后您只需通过摘要(不可变标识符)提取这些图像

$ docker pull node@sha256:the-image-digest-here

or

或者

$ docker pull node@sha256:26eb6780e26887a6838684a549562c0404fd85c55f71e0af6c79a4da5505d2a7

If you are lucky images corresponding to those digests are still available into the docker hub.

如果幸运的话,与这些摘要相对应的图像仍然可以在 docker hub 中使用。

After that, is you are still facing latestimages I will suggest you to rename those images with a proper name and tag and pull them in your own docker hub repository to be able to use them directly...

在那之后,您是否仍然面对latest图像,我建议您使用适当的名称和标签重命名这些图像,并将它们拉入您自己的 docker hub 存储库中,以便能够直接使用它们...