Monitor the Existence of Docker Images in a Registry

Monitor the Existence of Docker Images in a Registry

Docker is everywhere. It's used for deploying cloud services (e.g. Kubernetes, Docker Compose), doing CI/CD (e.g. GitHub, GitLab) or monitoring systems (e.g. Checkson). Sometimes it's a good idea to monitor if a certain Docker image is still available in a registry, especially if the registry has a retention policy that deletes unused or untagged images after a period of time.

In this blog post, we will show you how to verify the existence of Docker images in a registry without pulling them, using the Docker CLI and a simple bash script. We will also show you how to use Checkson, a cloud-based service that runs your script and alerts you when images are missing.

Why do you need to verify the existence of Docker images?

There are several reasons why you may want to verify the existence of Docker images in a registry, such as:

  • Some Docker registries have a retention policy that limits the storage of Docker images, so they may get deleted after a certain period of time or when they reach a certain quota.

  • Some Docker images are pulled only infrequently, but are nevertheless important for your applications or workflows. For example, you may have some base images that you use to build other images, or some backup images that you use for disaster recovery.

How to verify the existence of Docker images using the Docker CLI?

One way to verify the existence of Docker images in a registry is to use the Docker CLI. The Docker CLI has a command called docker manifest that allows you to inspect the manifest of an image. The manifest is a JSON document that describes the image layers, configuration, and metadata.

In newer versions of Docker, the docker manifest command is available by default. To use the docker manifest command in older versions, you need to enable experimental features. You can do this by setting the environment variable DOCKER_CLI_EXPERIMENTAL=enabled or by editing the ~/.Docker/config.json file and adding "experimental": "enabled".

You can now use the docker manifest inspect command to check if an image exists in a registry. For example, to check if the image python:3.10 exists in the default Docker Hub registry, you can run:

docker manifest inspect python:3.10

If the image exists, you will see the manifest information printed on the screen. If the image does not exist, you will see an error message like:

no such manifest: docker.io/library/python:3.10

You can also specify a different registry by using the full image name. For example, to check if the
image quay.io/prometheus/node-exporter:v1.6.1 exists on quay.io, you can run:

docker manifest inspect quay.io/prometheus/node-exporter:v1.6.1

Note that if you use a private registry, you may need to authenticate with the registry before using the docker manifest inspect command. You can do this by using the docker login command with your registry credentials.

How to verify the existence of Docker images using a bash script?

Let's put this command in a bash script and check multiple images at once.

You loop over a list of image names, and use the docker manifest inspect command with each image name. Then, you can use the exit code of the command to determine if the image exists or not. The exit code is 0 if the image exists, and non-zero if it does not.

Here is an example of a script that checks if a list of images exists in a registry:

#!/bin/bash

# Define an array of image names
images=(
  ubuntu:latest
  alpine:latest
  busybox:latest
  myimage:latest
)

# Loop over the array
for image in "${images[@]}"; do
  # Check if the image exists using Docker manifest inspect
  docker manifest inspect "$image" > /dev/null 2>&1

  # Get the exit code of the command
  exit_code=$?

  # Print the result based on the exit code
  if [ $exit_code -eq 0 ]; then
    echo "$image exists"
  else
    echo "$image does not exist"
  fi
done

If you run this script, you will see something like:

ubuntu:latest exists
alpine:latest exists
busybox:latest exists
myimage:latest does not exist

How to use Checkson to monitor your Docker images?

If you want to monitor your Docker images and get notified when they are missing, you can use Checkson.

Let's modify the script from before somewhat so that it exits with a non-zero exit code if any of the images does not
exist. Let's also make it possible to specify the images as environment variables, so that the check is more reusable.

#!/bin/bash

# Check if images are configured
if [[ -z "$IMAGES" ]]; then
  echo "Please set the IMAGES environment variable"
  exit 1
fi

# Split images by comma
IFS=',' read -ra IMAGES <<< "$IMAGES"

for image in "${IMAGES[@]}"; do
  docker manifest inspect "$image" > /dev/null 2>&1

  # Get the exit code of the command
  exit_code=$?

  if [ $exit_code -eq 0 ]; then
    echo "$image exists"
  else 
    echo "$image does not exist"
    exit 1
  fi
done

echo "All images are present in the registry"
exit 0

You can now wrap this script in a Docker image using the following Dockerfile:

FROM docker:24-cli

COPY . /app
WORKDIR /app

RUN apk add --no-cache bash

ENTRYPOINT ["bash", "check.sh"]

The image is based on the docker:24-cli image which includes the Docker command line tool. It does not, however, include bash, so you have to install this package using apk add --no-chache bash.

After you have built the Docker image and pushed it to a registry (let's assume you have used the tag someuser/docker-images-present-check:1.0), you can create an automated check using the Checkson CLI:

checkson create image-check \
  --image someuser/docker-images-present-check:1.0 \
  --email me@example.com \
  --env IMAGES=ubuntu:latest,alpine:latest,busybox:latest,myimage:latest \
  --check-interval 120

You will now receive an email if any of the configured images is missing.

Conclusion

In this blog post, we have shown you how to verify the existence of Docker images in a registry without pulling them, using the Docker CLI and a bash script. We have also shown you how to use Checkson to monitor the images continuously.

Note: There is a working example of this check on GitHub.