Skip to content

--version always reports CRITICAL for multi-arch images (compares manifest-list digest to per-arch config digest) #110

@GerasDraugas

Description

@GerasDraugas

Summary

When a container runs a multi-arch (manifest-list) image, --version always returns CRITICAL ("version does not match registry"), even when the local image matches the registry tag exactly. This is a false positive. The check compares two different kinds of digest, so they can never be equal for these images.

Version

check_docker.py 2.3.0 (latest from master), on a linux/amd64 Docker host.

Reproduce

With any official multi-arch image, for example valkey/valkey:9:

docker pull valkey/valkey:9
docker compose up -d --force-recreate
check_docker.py --containers mycontainer --version

Output:

CRITICAL: mycontainer's version does not match registry

The CRITICAL stays after docker image prune, docker compose pull, a plain docker pull, and --force-recreate. The pull itself confirms there is nothing to update: Status: Image is up to date for valkey/valkey:9.

Root cause

The two sides of the comparison return different digest types.

Local side: get_container_image_id returns inspection['Image']. For a multi-arch pull this is the manifest-list digest.

Remote side: get_digest_from_registry resolves the manifest list to the host's per-arch manifest with find_digest_for_architecture, fetches that manifest, then returns registry_info['config']['digest'], which is the image config blob digest.

For a multi-arch image these are three separate values:

manifest-list digest : sha256:4963247afc4cd33c7d3b2d2816b9f7f8eeebab148d29056c2ca4d7cbc966f2d9   (local .Image / RepoDigest)
amd64 manifest digest: sha256:e30fbdc8d6d6b355712e50f4008321026f69db3e450254b4f0008d22745d8d0e
amd64 config digest  : <a third sha256>                                                          (what the check compares against)

Because the local value is the manifest-list digest and the remote value is the per-arch config digest, registry_hash == image_id is never true, so the check always falls through to CRITICAL.

Expected

The check should compare matching digest types. Two options that would work: compare the local container's resolved per-arch config digest against the remote per-arch config digest, or compare the local RepoDigest (manifest-list digest) against the registry's manifest-list digest (the tag's Docker-Content-Digest). Either avoids mixing manifest-list and config digests.

Impact

Official multi-arch tags are very common, so any deployment that uses them gets a permanent false CRITICAL from --version. That makes the stale-image check unusable for those images.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions