docker『Image Digest Does Not Match』の原因と対処法
- 作成日 2025.12.01
- その他
イメージの「内容を表すハッシュ値(digest)」が、クライアント・レジストリ・マニフェストなどで一致せず、pull や deploy、検証処理が止まる状態。レジストリ側のタグ更新、CDN/ミラーの不整合、プラットフォームごとのマニフェスト差、ローカルキャッシュの破損、セキュリティ検証ツールの期待digestとのズレなど、発生源は広い。まず「どこで計算されたどのdigestと、どのdigestが一致しないのか」を特定することが重要になる。
エラーの意味と典型的な発生条件
「Image Digest Does Not Match」系のエラーは、主に次のような状況で出る。
・docker pull の完了時に、取得したイメージの digest がマニフェストの記載と一致しない。
・Kubernetes や CI/CD が「期待するdigest」と実際のイメージのdigestを比較して検証した結果、一致しない。
・コンテンツトラスト / 署名検証(Notary, cosign など)の内部で digest 不一致が検出される。
・レジストリミラーやキャッシュプロキシが古いマニフェストを返し、実体と合っていない。
・レジストリ側のタグ付け・再pushにより、digest が書き換わったあとで古いdigestを参照している。
イメージダイジェストとは何か(タグとの違い)
タグとdigestの違いを押さえると、エラーの意味がつかみやすくなる。
・tag:人間が付けるラベル(例: :latest, :1.0.0)。後から別のイメージに付け替え可能。
・digest:イメージ内容(マニフェストやレイヤ)から計算されるハッシュ値(例: sha256:xxxx…)。内容が変わればdigestも変わる。
# digest付きでイメージを指定する例
docker pull nginx@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
# ローカルイメージのdigestを確認
docker images --digests nginx
# 詳細マニフェストとdigestの確認
docker inspect nginx:1.25 | jq '.[0].RepoDigests'
digest不一致は、「同じタグなのにdigestが変わっている」あるいは「同じdigestのはずが実体が異なる」といった状態で起きやすい。
docker pull / run 時に digest 不一致が出る場合
pull 直後に「digest does not match」系のエラーが出る場合、次のような原因が考えられる。
・レジストリ側でタグ更新が行われ、ダウンロード途中にマニフェストが変わった。
・レジストリミラー/CDNが古いマニフェストを返している。
・ネットワークエラーやキャッシュ破損で、一部レイヤが壊れている。
対処の基本は「キャッシュの破棄」と「再pull」。
# 該当イメージのローカルキャッシュを削除してからpull
docker image rm nginx:1.25 || true
docker image rm nginx@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa || true
# system全体の不要データを掃除(検証環境で)
docker system prune -a
# 再pull
docker pull nginx:1.25複数ノード(Kubernetesなど)でpullしている場合、クラスタ内のノードごとに状況を揃える必要がある。
レジストリミラー・キャッシュプロキシ・CDNの不整合
プライベートレジストリにミラーやキャッシュを挟んでいる環境では、digest不一致が「キャッシュ側≠オリジナル」という形で起きることがある。
・ミラーが古いマニフェストを返し、pull自体は成功するが、後続の検証でdigest不一致が検出される。
・レジストリ側のGCや再構成で、一部のレイヤが消えている。
# ミラー経由ではなく、オリジナルレジストリを直接指定してpull
docker pull registry.example.com/myorg/app:1.0
# オリジナルとミラーの両方でdigestを比較
docker manifest inspect registry.example.com/myorg/app:1.0 | jq .config.digest
docker manifest inspect mirror.example.com/myorg/app:1.0 | jq .config.digest
・digestやマニフェストがズレている場合は、ミラー側のキャッシュクリア、再同期、設定見直しが必要になる。
CI/CDやKubernetesで「期待digest」と合わない場合
デプロイ時に「このdigestであること」を前提にしている場合、イメージの更新やタグの付け替えでエラーが出る。
・Manifest / Helm / Kustomize などで digest を固定している。
・Policyエンジンやセキュリティスキャナが「許可されたdigest一覧」と比較している。
# Kubernetes Manifestでdigest固定している例
apiVersion: apps/v1
kind: Deployment
spec:
template:
spec:
containers:
- name: app
image: registry.example.com/myorg/app@sha256:aaaaaaaaaaaaaaaa...
# 実際のレジストリのdigestを確認
docker manifest inspect registry.example.com/myorg/app:1.0 | jq .config.digest
– レジストリ側でイメージを再ビルド/再pushした場合、digestが変わるのでManifestも更新する必要がある。
– 「digestを変えずに書き換える」ことは基本的にできないため、digest不一致が出た時点でイメージ内容は別物だと判断する。
マニフェストリスト(マルチアーキテクチャ)と digest 不一致
buildx やマルチアーキtectureイメージを使うと、1つのタグに対して複数プラットフォーム分のdigestが紐づく。
・manifest list(インデックス)と、個々のplatform向けイメージのdigestが別物になる。
# マニフェストリストの中身を確認
docker buildx imagetools inspect myorg/app:1.0
# 特定プラットフォームのdigest確認(例: linux/amd64)
docker buildx imagetools inspect myorg/app:1.0 \
| jq '.manifests[] | select(.platform.architecture=="amd64") | .digest'
プラットフォームごとのdigestを期待しているツールが、manifest list側のdigestを比較していると「一致しない」ように見える場合がある。
・どのdigest(manifest listなのか、特定platformイメージなのか)を使うべきか、ツール側の仕様に合わせて比較対象を揃える。
ローカルキャッシュの破損・コンテンツトラストの検証失敗
ディスク障害や中断されたpullなどにより、ローカルのlayerファイルが壊れている場合も digest mismatch の原因になる。
# 疑わしいイメージを完全に消してから再pull
docker image rm myorg/app:1.0 || true
docker builder prune -a
docker system prune -a
docker pull myorg/app:1.0Docker Content Trust(Notary)やサードパーティの署名検証を有効化している場合、署名でカバーされているdigestと実体のdigestが違うと検証失敗になる。
# Docker Content Trust例(環境変数でON)
export DOCKER_CONTENT_TRUST=1
docker pull myorg/app:1.0 # 署名に基づきdigest検証・署名されたイメージを更新するときは、新しいdigestで再署名し、トラストサーバに公開し直す必要がある。
セキュリティ上の疑いがあるケース(改ざん・MITMなど)
digest不一致は単なる設定ミスだけでなく、セキュリティインシデントの兆候である可能性もゼロではない。
・信頼できないネットワーク経由でレジストリにアクセスしている。
・レジストリの権限管理が甘く、誰かが同じタグに別のイメージを上書きしている。
・中間プロキシやキャッシュが疑わしい挙動をしている。
このような可能性がある場合は、以下のような追加確認を行う。
# 手元の別環境からも同じレジストリ/digestを確認
docker manifest inspect registry.example.com/myorg/app:1.0 | jq .config.digest
# 署名ツール(例: cosign)で検証(概念例)
cosign verify registry.example.com/myorg/app@sha256:aaaaaaaaaaaaaaaa...
改ざんが疑われる場合は、レジストリのアクセスログ・署名履歴・CI/CDログを確認し、異常なpushがないかを追跡する。
NG→OK 早見表(よくあるパターン別の修正例)
# 1) レジストリでタグを再pushしたのに、古いdigestをManifestで参照している
# NG(deployment yaml内)
image: registry.example.com/myorg/app@sha256:old_digest
# OK: 新しいdigestに更新(レジストリのdigestを確認して反映)
image: registry.example.com/myorg/app@sha256:new_digest
# 2) ミラー経由でdigest不一致
# NG: mirror.example.comだけを参照
docker pull mirror.example.com/myorg/app:1.0
# OK: オリジナルを直接参照しdigestを確認
docker pull registry.example.com/myorg/app:1.0
docker manifest inspect registry.example.com/myorg/app:1.0 | jq .config.digest
# 3) ローカルキャッシュ破損時
# NG: 何度も同じpullを繰り返すだけ
docker pull myorg/app:1.0
# OK: キャッシュ削除→再pull
docker image rm myorg/app:1.0 || true
docker system prune -a
docker pull myorg/app:1.0
# 4) マルチアーキtectureでプラットフォームdigestを混同
# NG: manifest list digestとamd64 digestを比較して「不一致」
# OK: 比較対象をそろえる
docker buildx imagetools inspect myorg/app:1.0 \
| jq '.manifests[] | select(.platform.architecture=="amd64") | .digest'
チェックリスト(上から順に潰す)
1) エラーが出ているのは「どのツール/処理」か(docker pull / deploy / 署名検証など)を特定したか
2) レジストリ上の最新digestを docker manifest inspect で確認したか
3) ローカルイメージの RepoDigests とレジストリのdigestを比較したか
4) ミラー/キャッシュプロキシ経由の場合、オリジナルレジストリとdigestが一致しているか
5) マルチアーキtectureイメージの場合、比較対象がmanifest listなのかplatform別digestなのかを意識したか
6) ローカルキャッシュ破損の可能性を排除するため、該当イメージを削除し再pullしたか
7) CI/CDやKubernetes Manifestでdigest固定している場合、イメージ更新に合わせてdigestを更新したか
8) 不審なdigestの変化がセキュリティインシデントでないか、レジストリログや署名履歴を確認したか
-
前の記事
docker『Timeout Reached』の原因と対処法 2025.11.27
-
次の記事
docker『Invalid Container Name』の原因と対処法 2025.12.02
コメントを書く