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.
Summary
When a container runs a multi-arch (manifest-list) image,
--versionalways 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:Output:
The CRITICAL stays after
docker image prune,docker compose pull, a plaindocker 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_idreturnsinspection['Image']. For a multi-arch pull this is the manifest-list digest.Remote side:
get_digest_from_registryresolves the manifest list to the host's per-arch manifest withfind_digest_for_architecture, fetches that manifest, then returnsregistry_info['config']['digest'], which is the image config blob digest.For a multi-arch image these are three separate values:
Because the local value is the manifest-list digest and the remote value is the per-arch config digest,
registry_hash == image_idis 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.