Docker Hub の取得失敗を先に分類する
「Docker pull が遅い」「Docker Hub からイメージを取得できない」「docker login は通るのに、実際の取得で context deadline exceeded が出る」——この種の問題は、単純に Docker Hub が落ちているとは限りません。Docker のイメージ取得は、最初にレジストリの API へ接続し、その後に認証トークンを受け取り、さらにレイヤー本体を別の CDN やストレージ配信先からダウンロードする構成になっています。
そのため、registry のメタデータだけ取得できるがレイヤーで止まる、認証だけ失敗する、名前解決に時間がかかる、Docker Desktop は動くが Linux サーバー上の Docker daemon は直行するといった症状が発生します。Clash を導入する場合も、ブラウザのシステムプロキシをオンにするだけでは十分ではありません。Docker CLI の通信主体は多くの環境で Docker daemon であり、CLI と daemon が別のネットワーク名前空間や VM 内で動いている場合、Clash の設定が届く場所も変わります。
前提:ここでは自分が管理する PC、開発サーバー、CI 環境で、正規の Docker Hub アカウントと利用規約に従って通信を分流する方法を扱います。組織ネットワークでは、プロキシ利用や外部レジストリへの接続について管理者のルールを優先してください。
DNS・認証・レイヤー取得を分けて確認する
最初から YAML を大きく書き換えるより、失敗した段階を特定した方が安全です。Docker Hub の取得では、次のような宛先が関係します。ただし実際のホスト名や CDN は変更される可能性があるため、固定リストを盲目的に信頼せず、Clash の接続ログで確認してください。
- レジストリ API:
registry-1.docker.ioへの HTTPS 接続。マニフェストやタグ情報の取得に使われます。 - 認証:
auth.docker.ioへのトークン要求。ここで失敗すると、イメージ名が正しくても pull は進みません。 - コンテンツ配信:マニフェスト取得後に、レイヤーを配信する CDN やオブジェクトストレージへ接続します。ここが広いドメインルールから漏れると、認証成功後にだけタイムアウトします。
- 名前解決:DNS が Clash の外側で行われると、到達性の悪いアドレスを返したり、分流判定に必要な情報と実際の接続先がずれたりします。
再現時は、まず docker pull alpine:latest のような小さな公開イメージでテストし、続けて実際に失敗するイメージを試します。Clash の接続一覧では、エラーが表示された時刻の前後に docker.io、docker.com、registry-1.docker.io、auth.docker.io が出ているかを確認します。何も記録されない場合は、Docker daemon が Clash を経由していません。記録はあるのに一部の宛先だけ DIRECT なら、ルールまたは DNS の問題を疑います。
Mihomo で Docker Hub 用の分流を作る
Clash のルールは、広い GEOIP や地域別ルールより前に、Docker Hub の明示的な宛先を置くのが基本です。専用のプロキシグループを作っておくと、通常の Web 閲覧用ノードとコンテナ取得用の経路を分けられます。まずは次のように、確認できた主要ドメインだけを対象にします。
proxy-groups:
- name: DOCKER_HUB
type: select
proxies:
- Proxy
- DIRECT
rules:
- DOMAIN,registry-1.docker.io,DOCKER_HUB
- DOMAIN,auth.docker.io,DOCKER_HUB
- DOMAIN-SUFFIX,docker.io,DOCKER_HUB
- DOMAIN-SUFFIX,docker.com,DOCKER_HUB
- MATCH,DIRECT
上の例で重要なのは、DOCKER_HUB を作ること自体より、ルールの順序とログによる検証です。すでにプロファイルに GEOIP,CN,DIRECT や大きなルールプロバイダがある場合、Docker 用ルールをその下に追加すると先に別ルールへ一致します。専用ルールは一般ルールより上に置き、変更後はプロファイルを保存してコアを再起動します。
ただし、レイヤー配信先がログに表示された場合は、それを確認してから必要なルールを追加してください。最初から広い CDN や全インターネットをプロキシへ送ると、通信量、遅延、アカウントの監査範囲が不必要に大きくなります。目的は「Docker Hub に必要な宛先だけを安定した経路へ送る」ことであり、無制限のグローバルプロキシ化ではありません。
Docker daemon を TUN・透過プロキシへ接続する
システムプロキシの設定だけで Docker が通るかどうかは、実行環境によって異なります。Linux で Docker Engine をホスト上に直接動かしている場合、daemon は root 権限のサービスとして動作し、ユーザーシェルの HTTP_PROXY やデスクトップのプロキシ設定を自動的に引き継ぐとは限りません。Docker Desktop では Linux VM 内の daemon が取得処理を担当するため、ホスト側でブラウザが通っていても、VM 側から Clash へ到達できるとは限りません。
- Clash の待受ポートを確認:混合ポート、または HTTP/SOCKS ポートがローカルだけで待ち受けているか確認します。Docker daemon が別 VM や別ホストにある場合、
127.0.0.1はその daemon 自身を指すため、ホスト側の Clash には届きません。 - TUN を有効化:Mihomo 対応クライアントで TUN をオンにし、
auto-route、auto-detect-interfaceを環境に合わせて設定します。TUN はアプリがプロキシ環境変数を理解しない場合でも IP 通信を捕捉できます。 - DNS の経路を揃える:Clash の DNS を使う構成では、Fake-IP または Redir-Host の方式を選び、Docker daemon が別の DNS へ直接問い合わせないようにします。社内 DNS や VPN と併用する場合は、内部ドメインを誤って外部へ送らない例外も必要です。
- ローカル宛先を除外:Docker のブリッジネットワーク、ホストの管理用アドレス、社内レジストリなどは、必要に応じて
DIRECTまたは bypass にします。これを怠ると、コンテナ間通信やプライベートレジストリまで外部ノードへ送られることがあります。 - 接続ログで再現:設定を有効にした状態で同じ
docker pullを実行し、Clash の接続一覧に Docker Hub の宛先と選択されたグループが表示されることを確認します。
Docker daemon に対して明示的な HTTP プロキシを設定する方法もあります。systemd 管理の Linux では、Docker のサービス設定に HTTP_PROXY、HTTPS_PROXY、NO_PROXY を与え、daemon を再読み込みしてから再起動します。ここで指定するプロキシは daemon から到達できるアドレスでなければなりません。Docker Desktop や CI の実行者が別環境にいる場合は、ホスト名、VM のゲートウェイ、ファイアウォールの許可範囲を個別に確認してください。
[Service]
Environment="HTTP_PROXY=http://127.0.0.1:7890"
Environment="HTTPS_PROXY=http://127.0.0.1:7890"
Environment="NO_PROXY=localhost,127.0.0.1,.local,registry.internal.example"
注意:上の 127.0.0.1:7890 は、Docker daemon と Clash が同じネットワーク名前空間にいる場合だけ使えます。Docker Desktop の VM、リモート Linux、Kubernetes ノードでは、そのままコピーせず、daemon から見える Clash のアドレスへ置き換えてください。
運用時の監視とトラブルシューティング
一度 pull が成功しても、ノードの自動切り替えや DNS の変更で再発することがあります。Docker のレイヤー取得は複数の HTTPS 接続を並行して開くため、短時間の接続数制限、出口ノードの混雑、TLS セッションの切断が目立つ場合があります。最初は自動選択グループではなく、安定性を確認しやすい固定ノードを選び、同じイメージを複数回取得して結果を比べると原因を追いやすくなります。
ログを見るときは、単に「接続できたか」だけでなく、どのルールに一致したか、どのグループへ送られたか、DNS 応答にどれくらい時間がかかったかを確認します。メタデータ取得は成功しているのにレイヤーだけ失敗するなら、新しい配信ホストを記録してルールを追加します。すべての宛先が DIRECT なら TUN、daemon のプロキシ継承、または Docker Desktop の VM 経路を確認します。Clash に記録があるのに Docker 側が失敗する場合は、証明書検査、MTU、プロキシが大きなレスポンスを途中で切っていないかを調べます。
- 名前解決だけ遅い:Clash DNS と Docker ホストの DNS が競合していないか、IPv6 の経路だけ失敗していないか確認します。
- 認証で失敗する:Docker Hub のログイン状態、時刻ずれ、認証用ホストのルール、企業プロキシの TLS 検査を確認します。
- レイヤー途中で切れる:ノードの帯域と同時接続数、MTU、CDN 宛先の分流を確認し、まず固定ノードで再現します。
- CI だけ失敗する:ローカルの Clash ではなく、Runner やビルドホストの daemon がどこから通信しているかを調べます。
同じイメージを何度も取得する開発環境では、社内のレジストリミラーや pull-through cache を使う方が、毎回 Docker Hub へ接続するより管理しやすい場合があります。その場合は内部レジストリを NO_PROXY と DIRECT の対象にし、外部 Docker Hub への同期処理だけを管理された経路へ送ります。機密イメージを扱う環境では、認証情報、レイヤー内容、プロキシログの保存先も合わせて確認してください。
一般的な VPN クライアントだけで Docker Hub を安定させようとすると、Docker daemon や仮想マシンの通信を拾えない、DNS だけ別経路になる、除外設定を細かく管理できないといった制約が出やすくなります。一方、Clash 公式サイト は Mihomo の TUN、ルール分流、DNS 制御、接続ログを一つの確認手順にまとめやすく、Docker Hub の必要な宛先だけを段階的にプロキシへ送れます。複雑な透過プロキシ設定を最初から一括適用するのではなく、まず小さな公開イメージで挙動を確認してから運用へ広げたい方は、Clash 公式サイト をダウンロードして、手元の Docker 環境で安全に試してみるとよいでしょう。