DOCKER_CONTENT_TRUST=1 docker pull alpine:latest
すると以下のエラーが出るようになった。$ DOCKER_CONTENT_TRUST=1 docker pull alpine:latest could not validate the path to a trusted root: unable to retrieve valid leaf certificates
ローカルの Docker(28.1.1, build 4eba377)でも、GitHub Actions の Ubuntu ランナーでも同じエラーがでるようになりました。
trusted root
とあるので「いつもの CA ファイル系か」と思い、ca-certificates
をアップデートしても同じ。「認証ファイルの更新を待てばいいか」とも思ったのですが、どうやら DOCKER_CONTENT_TRUST
自体が今後使えなくなるっぽい。
TL; DR (今北産業)
-
原因:
- 2025年8月以降、公式イメージの署名証明書が順次期限切れとなり、
DOCKER_CONTENT_TRUST=1
を設定したままではdocker pull
が失敗する
- 2025年8月以降、公式イメージの署名証明書が順次期限切れとなり、
-
回避策:
-
DOCKER_CONTENT_TRUST
を無効化する(DOCKER_CONTENT_TRUST=0
にする、または環境変数を外す)
-
-
理由:
-
誰も
DOCKER_CONTENT_TRUST
(DCT)を使っていないからDCT の仕様である
Notary
v1 もメンテナンスされていないので、DCT の廃止を決めた。コンテナ・イメージの署名と検証が必要な場合は、Notary
v2 に準拠した Sigstore や Notation への移行が推奨されている。
-
まさか DCT イメージを pull
する人が 0.05% 以下だとは。
TS; DR (kwsk)
DOCKER_CONTENT_TRUST
が使えなくなるですって?
docker
コマンドの -D
オプションでデバッグ情報を見ると DCT(Docker Content Trust)の仕組みで使われている「署名証明書の期限切れ」が原因とわかります。
$ DOCKER_CONTENT_TRUST=1 docker -D pull alpine:latest
time="2025-08-31T11:42:27+09:00" level=debug msg="reading certificate directory: /Users/admin/.docker/tls/notary.docker.io"
time="2025-08-31T11:42:28+09:00" level=debug msg="Making dir path: /Users/admin/.docker/trust/tuf/docker.io/library/alpine/changelist"
time="2025-08-31T11:42:28+09:00" level=debug msg="entered ValidateRoot with dns: docker.io/library/alpine"
time="2025-08-31T11:42:28+09:00" level=debug msg="found the following root keys: [a2489bcac7a79aa67b19b96c4a3bf0c675ffdf00c6d2fabe1a5df1115e80adce]"
time="2025-08-31T11:42:28+09:00" level=debug msg="a2489bcac7a79aa67b19b96c4a3bf0c675ffdf00c6d2fabe1a5df1115e80adce is invalid: certificate with CN docker.io/library/alpine is expired"
time="2025-08-31T11:42:28+09:00" level=debug msg="didn't find any valid leaf certificates for docker.io/library/alpine"
time="2025-08-31T11:42:28+09:00" level=debug msg="error retrieving valid leaf certificates for: docker.io/library/alpine, no valid leaf certificates found in any of the root keys"
could not validate the path to a trusted root: unable to retrieve valid leaf certificates
このことから「まぁ、証明書の更新って何気に面倒だもんなぁ。Docker 社でもそういうことあるんだぁ」と理解を示しつつ、しばらく放置していました。Alpine の Docker イメージでは、CA 系のエラーはちょくちょくあったし。
しかし、更新される気配がありません。ブックマークしていた、公式の "Content trust in Docker" のページも定期的にチェックしていたのですが、何もアナウンスはありませんでした。
1ヶ月程度経過して、さすがに何か起きていると思い「docker "could not validate the path to a trusted root" "unable to retrieve valid leaf certificates"」でググってみたのですが、有用な情報はヒットしませんでした。
そこで ChatGPT の deep research
で関連情報を調べてもらったところ、「7 月末に、公式ブログで DOCKER CONTENT TRUST
がリタイアすることがアナウンスされている」ことを知りました
- Retiring Docker Content Trust | blog @ docker.com
しかも、定期チェックしていた公式ドキュメントのページではなく、別のページで明記されていることもわかりました。
Note
Docker is retiring Docker Content Trust (DCT) for Docker Official Images (DOI). Starting on August 8th, 2025, the oldest of DOI DCT signing certificates will begin to expire. You may have already started seeing expiry warnings if you use the docker trust commands with DOI. These certificates, once cached by the Docker client, are not subsequently refreshed, making certificate rotation impractical. If you have set the DOCKER_CONTENT_TRUST
environment variable to true
(DOCKER_CONTENT_TRUST=1
), DOI pulls will start to fail. The workaround is to unset the DOCKER_CONTENT_TRUST
environment variable. The use of docker trust inspect
will also start to fail and should no longer be used for DOI.
For more details, see https://www.docker.com/blog/retiring-docker-content-trust/.
- Docker Official Images | Trusted content @ docs.docker.com より
筆者訳
Dockerは、DOI(Docker 公式イメージ)向けの DCT(Docker Content Trust)の提供を終了します。
2025 年 8 月 8 日より、DOI の DCT 署名証明書の最も古いものが順次失効し始めます。DOI に対して docker trust
コマンドを使用している場合、既に失効警告が表示されている可能性があります。
これらの証明書は、Docker クライアントによって一度キャッシュされると、その後も更新されないため証明書のローテーションも現実的でなくなってきます。
つまり、DOCKER_CONTENT_TRUST
環境変数を true
(DOCKER_CONTENT_TRUST=1
)に設定している場合、DOI の pull
操作が失敗し始めます。
回避策として、DOCKER_CONTENT_TRUST
環境変数を解除してください。docker trust inspect
の使用も失敗し始めるため、DOI に対しては使用を中止してください。
なんと言うことでしょう。DOCKER_CONTENT_TRUST
は使えなくなるんですって。
Docker の公式イメージの代替
そもそも「Docker 公式イメージ」(DOI)は、Docker 側が作って(ビルドして)いるものではありません。
その名前から私も長いこと誤解していたのですが、身元確認が取れたソースコードの公式側がビルドしてプッシュしたものです。つまり、「公式」と言うより「公認」に近い気がします。
そのため、必ずしも公式のリリースに自動的に追随するもではありませんでした。
以前より、イメージによってアップデートにバラつきがあったため、Docker の中の人の大人の都合や好みでアップデートされていると思い込み、調べたところ勘違いであったことを知ったのでした。
しかし、昨今の「少なくともベースとなるイメージは安全なものを使いたい」というニーズに対し、Docker 側が CVE の少ない安全なイメージを Docker Hardened Images として有償で公開するようになったことは知っていました。
そして DOCKER_CONTENT_TRUST
が使えなくなることで「この守銭奴がっ!」と安易に思ってしまいましたが、さらに調べてみると、そうとも言えなさそうです。
そもそも、コンテナ技術は Docker 社の特許ではなく、OCI という規格に準拠したものです。
Docker のモノポリ感は否めないものの、この規格に準拠したイメージであれば、docker
に限らず Podman などの、他のコンテナ・ツールでも利用できます。利便性の違いだけです。
そうなると、「安全なイメージの作成と提供はコード・オーナー側にある」ということになります。
つまり、この作業をおろそかにしている公式に対し、代替策として Docker 社は有償で動作確認・脆弱性チェックを行い Docker Hardened Images
を公開しているということになります。
とは言え、WASM コンテナの仕様が OCI 1.1.0 でも制定されたことにより、今後もコンテナを使うことがさらに増えるのは必至です。有償・無償関係なく「安全なイメージ」の需要は高まることになります。
「安全か」という判断にはコストがかかります。しかし、少なくとも「公式からリリースされたイメージである」と利用側が検証できるだけでも、セキュリティはグッと高まります。
Docker 社もそれはわかっていて、「イメージを公開鍵暗号で署名と検証をする仕組み」を決める Notary
というプロジェクトを進めていたのですが、Notary
が v2 になった時点で、プロジェクトをコミュニティ(CNCF)に寄贈しました。
そして、自分達は有償版(商用向け)に専念するというスタンスを取りました。良くも、悪くも RedHat 社と似たビジネス・モデルです。
実は、この Notary
の v1 が Docker Content Trust
の事だったりします。
Notary v2
のバージョンアップと共に、Docker Content Trust
を廃止し、
そして、この Notary
を実装したものが Notation
とうツールです。
もともと、CNCF も Sigstore というプロジェクトで、独自仕様の "Cosign" という署名・検証ツールを持っていました。
似た機能ではあるのですが、競合と言うより、現在は Notary
の仕様(現在の仕様は v2)をお互いに補完しあうツールとなっている印象を受けます。近い将来、統合されるかもしれません。
まとめると、以下のようにいえます。
- OCI に準拠したコンテナ・イメージに対して「署名と検証に関する仕様」が
Notary
-
Notary
は Docker の手から離れて、現在は CNCF 管理下にある -
Notary
の最新仕様はNotary
v2 - Notation と Cosign は
Notary
v2 に準拠した実装(アプリ) -
Docker Content Trust
は Notary v1 時代の仕様で廃止になる予定
さて、DOCKER_CONTENT_TRUST
の環境変数も、docker trust inspect
も使えなくなることから、やはり今後の代替案が欲しくなります。
かと言って、オープンソースでしかコードを公開していないため Docker Hardened Images
を使うほどの👌もありません。
結論から言うと、2025 年 09 月現在、コンテナのレジストリに Docker Hub を中心に運用している場合は「pull
したイメージは検証しない」という漢らしい選択肢(仕様割り切り)になります。
というのも、Notary
の立役者である Docker 自身(Docker Hub)が Notary
v2 に対応していないのです。
notation
をローカルにインストールしたので、docker pull alpine:latest
で pull
したイメージを検証しようとしたところ、以下の署名されていないエラーが出ました。
$ notation version
Notation - a tool to sign and verify artifacts.
Version: v1.3.2+unreleased
Go version: go1.25.0
$ docker pull alpine:latest
latest: Pulling from library/alpine
9824c27679d3: Pull complete
Digest: sha256:4bcff63911fcb4448bd4fdacec207030997caf25e9bea4045fa6c8c44de311d1
Status: Downloaded newer image for alpine:latest
docker.io/library/alpine:latest
What's next:
View a summary of image vulnerabilities and recommendations → docker scout quickview alpine:latest
$ notation verify docker.io/library/alpine:latest
Warning: Always verify the artifact using digest(@sha256:...) rather than a tag(:latest) because resolved digest may not point to the same signed artifact, as tags are mutable.
Error: signature verification failed: no signature is associated with "docker.io/library/alpine@sha256:4bcff63911fcb4448bd4fdacec207030997caf25e9bea4045fa6c8c44de311d1", make sure the artifact was signed successfully
Signer や GitHub Container Registry など、他のコンテナ・レジストリなどで利用可能かわかりしだい、別の記事にしたいと思います。