Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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 ps is just showing me that the containers use the "latest" or no tag, like this:

# 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.

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.

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?

Docker version: 18.09.1, build 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)

function getDigestByImageNameWithTag () {
    TARGET_IMAGE_NAME_WITH_TAG="$1" # 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="$1"
    TARGET_DIGEST="$2"

    # 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 $2}' | 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?

like image 784
Forivin Avatar asked Jun 18 '19 10:06

Forivin


People also ask

How do I see all images in docker?

The easiest way to list Docker images is to use the “docker images” with no arguments. When using this command, you will be presented with the complete list of Docker images on your system. Alternatively, you can use the “docker image” command with the “ls” argument.

How do I list a running docker container?

In order to list the Docker containers, we can use the “docker ps” or “docker container ls” command. This command provides a variety of ways to list and filter all containers on a particular Docker engine.

What is my docker image tag?

Docker Image tags are simple labels or aliases given to a docker image before or after building an image to describe that particular image. It can be the version of the project or the container, features of the image, technologies used in the image or pretty much anything you want.

Which command to see all the commands that were run with an image via container?

docker history With this command, you can see all the commands that were run with an image via a container.


2 Answers

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 inspect $(docker ps  | awk '{print $2}' | 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 jq get all repo tags of that image.

Here is the output.

docker images tags and name

Updated:

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

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

running_container=$(docker ps  | awk '{print $2}' | grep -v ID) 
echo "running container: $running_container"
for image in $running_container
do
local_tag=$(echo "$image" | awk -F":" '{print $2}')
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 $2}' | 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

like image 86
Adiii Avatar answered Oct 05 '22 06:10

Adiii


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

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

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

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.

like image 37
BMitch Avatar answered Oct 05 '22 07:10

BMitch