"could not validate the path to a trusted root: unable to retrieve valid leaf certificates"
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 をアップデートしても同じ。leaf certificates(関連証明書)とあるので「認証ファイルの更新を待てばいいか」とも思ったのですが、どうやら DOCKER_CONTENT_TRUST 自体が使えなくなっているっぽい。
TL; DR (今北産業)
-
原因:
- Docker 公式イメージ(DOI)関連の署名証明書が 2025年8月以降、順次期限切れとなり、
DOCKER_CONTENT_TRUST=1を設定したままではdocker pullが失敗し始めたから
- Docker 公式イメージ(DOI)関連の署名証明書が 2025年8月以降、順次期限切れとなり、
-
回避策:
-
DOCKER_CONTENT_TRUSTを無効化する
(DOCKER_CONTENT_TRUST=0にする、または環境変数を外す)
-
-
理由:
-
誰も
DOCKER_CONTENT_TRUST(DCT)を使っていないのである- DCT のイメージを
pullする人が 0.05% 以下であり、DCT の仕様であるNotaryv1 もメンテナンスされておらず、堅牢性チェックのマンパワーもないので、DCT の廃止を決めた - とは言え、セキュリティにうるさい企業勢のために、有料で堅牢なイメージを提供することにした
-
Notaryは、もったいないないので仕様をコミュニティに寄贈したら、v2 になった。今後、無償でコンテナ・イメージの署名と検証が必要な場合は、Notary v2 に準拠した Cosign や Notation を使った方法への移行が推奨されている
- DCT のイメージを
-
TS; DR (kwsk)
DOCKER_CONTENT_TRUST が使えなくなるですって?
冒頭の通りエラーが出るようになり、エラーの詳細が知りたかったので docker コマンドの -D オプションでデバッグ情報を見てみました。
$ DOCKER_CONTENT_TRUST=1 docker pull alpine:latest
could not validate the path to a trusted root: unable to retrieve valid
leaf certificates
$ DOCKER_CONTENT_TRUST=1 docker -D pull alpine:latest
time="2025-08-31T11:42:27+09:00" level=debug msg="reading certificate directory: /Users/KEINOS/.docker/tls/notary.docker.io"
time="2025-08-31T11:42:28+09:00" level=debug msg="Making dir path: /Users/KEINOS/.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
"certificate with CN docker.io/library/alpine is expired" とあります。やはり DCT(Docker Content Trust)の仕組みで使われている「署名証明書の期限切れ」が原因とわかります。
しかし、CA でなく CN(コモンネーム)と言うことは、docker.io 用のサーバー証明書が有効期限切れを起こしていることになります。
ここで、CA 以下にある特定の CN(ここでは docker.io)だけが期限切れを起こしている異常に気づけばよかったのですが、「まぁ、証明書の更新って何気に面倒だもんなぁ。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 で関連情報を調べてもらったところ、「2026 年 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 公認イメージ」に近い気がします。
Docker 公式のイメージの古さに対してコミュニティ側が「アップストリームが処理してくれないから」とよく見聞きしていたので、私も長いこと Docker 側がビルドしていると誤解していました。
てっきり Docker の中の人の「大人の都合」や「好み」でアップデートされていると思い込み、調べたところ筆者の勘違いであったことを知ったのでした。
つまり、コミュニティより上位のコードオーナーでないと(鍵がないため)イメージをプシュできないので、コミュニティ側では何もできないという意味だったのです。
このことから、コードオーナーが Docker に興味がない場合、必ずしも公式のリリースに自動的に追随するもではありませんでした。
しかし「少なくともベースとなるイメージは安全なものを使いたい」という昨今のニーズに対し、Docker 側が CVE の少ない安全なイメージを Docker Hardened Images として有償で公開するようになったことは知っていました。
そして、今回の DOCKER_CONTENT_TRUST が使えなくなることで「この守銭奴がっ!」と安易に思ってしまいましたが、さらに調べてみると、そうとも言えなさそうです。
Notary と Sigstore と CNCF
そもそも、コンテナ技術は 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 の事だったりします。
先のログの 1 行目を見ると「reading certificate directory: /Users/KEINOS/.docker/tls/notary.docker.io」と notary.docker.io という記述に気づくと思います(筆者は、気づかなかったのですが)。
しかし、0.05% 以下という利用者数が語っているように、企業主体の考えでは限界が見えてきました。そこで、Notary をコミュニティ(CNCF)に譲渡することで、今後の仕様はコミュニティに決定・判断してもらうという動きに至ったわけです。
そして、Notary v2 の新たな仕様が決まったと共に、Docker Content Trust の廃止が決定し、この Notary v2 を実装した Notation というツールも生まれました。
もともと、CNCF も Sigstore というプロジェクトで、独自仕様の「Cosign」という署名・検証ツールを持っていました。
「OCI イメージの署名と検証を提供するツール」と言う意味では、Cosign と Notation は似たツールです。しかし競合と言うより、Notary v2 の仕様をお互いに補完しあうツールとなっている印象を受けます。近い将来、統合されるかもしれません。
というのも、Sigstore の仕様はシンプルに適用できる反面、企業向け KMS 連携(AKV/AWS KMS など)や厳格な Trust Policy 運用には向かないという面もありました。
逆に Notary v2 の仕様は、いささか難しい反面、エンタープライズ向けの運用に向いています。
まとめると、以下のようにいえます。
- OCI に準拠したコンテナ・イメージに対して「署名と検証に関する仕様」が
NotaryとSigstore -
Notaryは Docker の手から離れて、Notaryv2 から CNCF 管理下にある - 現在
Notaryも、Sigstoreも CNCF 管理下にある -
Sigstoreの仕様はシンプルだがエンタープライズ(企業)向けに弱い -
Notaryの仕様は厳しいがエンタープライズ(企業)向けに強い -
Sigstoreの実装がcosignコマンド -
Notaryの実装がnotationコマンド -
cosignも、一部Notaryv2 の仕様に準拠しようとしている
さて、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
Docker によると、そもそも DOCKER_CONTENT_TRUST=true を気にしているユーザーは少ないらしいのですが、「いいね」が複数付いたら Signer や GitHub Container Registry などの利用方法を追記 or 記事にしたいと思います。