この記事で分かること
ブラウザや動画サイトは正常に表示できるのに、Docker Hub からイメージだけ取得できない、docker pull が数十秒待ってからタイムアウトする、またはマニフェスト取得までは進むのにレイヤーのダウンロードで止まる——この症状は、Docker がブラウザと同じプロキシ経路を使っていないときによく発生します。Clash のシステムプロキシをオンにしていても、Docker Engine、Docker Desktop の内部 VM、WSL、Linux 上の systemd サービスは、それぞれ異なる DNS とネットワーク設定を参照する場合があります。
本稿では、Docker Hub タイムアウトを「回線が遅い」という一言で片付けず、DNS 解決、ルール分流、TUN モード、Docker デーモンのプロキシ設定、MTU、IPv6 の順に切り分けます。Clash Verge Rev や Mihomo 系クライアントを前提にしていますが、OpenClash など別の Clash クライアントでも考え方は共通です。目的はすべての通信を無条件に迂回することではなく、Docker Hub に必要なホストを安定した経路へ送り、LAN 内のレジストリや社内サービスは必要に応じて DIRECT に残すことです。
なお、Docker Hub のエンドポイントや CDN は将来変更される可能性があります。設定例は出発点として利用し、最終的には Clash の接続ログに実際に表示されたホスト名、Docker のエラー内容、DNS の応答を突き合わせて調整してください。
Docker Hub だけタイムアウトする主な原因
Docker のイメージ取得は、単一の URL に一度接続して終わる処理ではありません。最初に認証用エンドポイントへアクセスし、次にレジストリ API からマニフェストを取得し、その後に CDN やストレージ側のホストから複数のレイヤーを並列ダウンロードします。そのため、最初の認証だけ成功しても、後続のレイヤー取得先が DIRECT に落ちれば、ユーザーには単純な「Docker Hub timeout」と表示されます。
- ブラウザと Docker のプロキシが別:ブラウザは OS のシステムプロキシを使っていても、Docker Engine は環境変数や daemon 設定を見ていないことがあります。
- Docker Desktop 内部 VM の経路が別:ホスト側で Clash の TUN を有効にしても、内部 VM の DNS や仮想ネットワークが同じ経路になるとは限りません。
- 認証とレイヤーのドメインが異なる:
registry-1.docker.ioだけをプロキシへ送っても、認証や CDN 側が DIRECT のままでは処理が完了しません。 - DNS の応答と実際の出口が合わない:Clash が返したアドレスへ接続しても、ルール判定が想定外なら、名前解決は成功したのに TCP 接続だけが失敗します。
- IPv6 や MTU の不整合:小さな HTTPS リクエストは通る一方、大きなレイヤーを転送すると再送が増え、タイムアウトのように見えることがあります。
まず「Docker Hub 全体が落ちている」と決めつけず、docker info、docker pull の詳細ログ、Clash の接続履歴を同じ時刻で確認します。ブラウザのページが開くかどうかだけでは、Docker の通信経路を証明できません。
DNS とルール分流を確認する
Clash で Docker Hub を安定させる第一歩は、DNS とルールを別々の問題として確認することです。DNS が名前を引けない場合はルール以前の問題ですが、名前が解決できても接続先が DIRECT へ送られていればタイムアウトは残ります。Clash のログを開き、docker pull を実行した瞬間にどのホストが表示され、どのポリシーグループへマッチしたかを確認してください。
代表的な確認対象には、レジストリ本体の registry-1.docker.io、認証で使われる auth.docker.io、イメージ情報や API に関係する hub.docker.com があります。レイヤー配信では Docker のストレージや CDN のホストが表示されることもあるため、三つのドメインだけを固定的に登録すれば必ず十分とは限りません。ログに現れたホストが MATCH や意図しない DIRECT に入っていないかを見て、必要な範囲だけルールを追加します。
| 確認対象 | 見るポイント | 対処の考え方 |
|---|---|---|
| DNS 解決 | Docker が使う環境から名前を引けるか | Clash の DNS モードと Docker 側の DNS を一致させる |
| 認証 | auth.docker.io の接続が成功するか |
認証ホストを安定したプロキシグループへ送る |
| レジストリ | マニフェスト取得後に切断されないか | registry-1.docker.io のルール判定を確認する |
| レイヤー配信 | 大きな Blob の転送だけ失敗しないか | ログに出た CDN・ストレージのホストを追跡する |
DNS 設定を変更した直後は、Docker デーモンや Docker Desktop を再起動してください。古い名前解決結果や既存の Keep-Alive 接続が残っていると、設定変更が反映されたように見えないことがあります。自宅 LAN のサービスや社内レジストリまでプロキシへ送る必要はないため、内部ドメインとプライベートアドレスは DIRECT にする設計も検討します。
TUN モードと Docker のプロキシ設定を使い分ける
TUN モードは、アプリケーションが HTTP プロキシ環境変数を読まない場合でも、ホストの通信を仮想インターフェースから Clash へ取り込める点が強みです。Docker CLI が直接通信しているように見える場合や、WSL、補助ツール、特定のコンテナ通信まで同じルールで扱いたい場合に有効です。ただし、TUN をオンにすれば自動的に Docker 全体が解決するわけではありません。TUN の自動ルート、DNS 拡張、IPv6、他の VPN やセキュリティソフトとの競合を確認する必要があります。
一方、Docker Engine 自体が外部レジストリへ接続する構成では、Docker デーモンへ明示的にプロキシを渡すほうが再現性の高い場合があります。Linux の systemd 管理では、シェルで HTTPS_PROXY を設定しただけでは daemon に届きません。Docker Desktop では GUI のプロキシ設定と、Clash のリスニングポートが別々に存在するため、どの層へ設定したかを記録しておくことが重要です。
設定を変更するときは、TUN と明示的な HTTP プロキシを同時に無計画で有効にしないでください。二重プロキシによるループ、HTTPS の CONNECT 失敗、localhost の除外漏れが発生する可能性があります。まずはシステムプロキシまたは Docker の HTTP プロキシだけで動作を確認し、プロセスが経路を無視するときに TUN を追加する順序が安全です。
| 構成 | 向いている場面 | 注意点 |
|---|---|---|
| HTTP/HTTPS プロキシ | Docker Engine の出口を明示したい | daemon、CLI、コンテナで設定箇所が異なる |
| TUN モード | プロキシ非対応プロセスも同じ経路にしたい | VPN、IPv6、DNS、ルート競合を確認する |
| システムプロキシ | ブラウザや一般的な GUI アプリを対象にする | Docker Engine が参照するとは限らない |
実際に行う切り分け手順
ここでは変更を最小限にしながら、どの層で止まっているかを確認します。作業前に現在の Clash プロファイル、TUN の状態、Docker Desktop のプロキシ設定をメモしておくと、変更を戻す際に迷いません。
- Clash のポートとログを確認する:HTTP プロキシの待受ポート、TUN の稼働状態、現在選択されているプロキシグループを確認します。接続ログはクリアしてから一回だけ
docker pullを実行すると、関連ホストを見つけやすくなります。 - DNS を環境ごとに調べる:ホスト OS、WSL、Docker コンテナ内で同じ名前が解決できるかを比較します。ホストだけ成功し、コンテナだけ失敗するなら、Clash より Docker の DNS 設定や仮想ネットワークを先に見ます。
- 小さな HTTPS 接続を確認する:認証ホストとレジストリへ接続し、DNS、TCP、TLS、HTTP のどの段階で止まるかを分けます。プロキシを指定した場合と指定しない場合を比較し、結果を混同しないようにします。
- ルール判定を修正する:ログに出た Docker 関連ホストを、必要なプロキシグループへ送ります。広いドメイン指定を追加する場合は、社内レジストリやローカル開発環境まで巻き込まないか確認してください。
- 一度に一つだけ変更する:DNS、TUN、MTU、Docker のプロキシを同時に変更すると、成功しても原因が分かりません。変更後は Docker Desktop または daemon を再起動し、同じイメージで再テストします。
イメージ取得が「認証成功後に停止」するなら、レジストリまたはレイヤー配信先を疑います。特定の大容量レイヤーだけで止まる場合は、ノードの混雑、MTU、接続の再利用、プロキシ側の転送制限を確認します。複数ノードを試すときも、速度だけでなく、同じイメージを二回取得したときの再現性を重視してください。
docker info
docker pull alpine:latest
docker system info
上のコマンドは状態確認の例です。実行結果に含まれる認証情報やプライベートレジストリの URL は、ログ共有前に削除してください。Docker のプロキシ設定を変更した場合は、実行中のコンテナへ自動で反映されるとは限りません。イメージ取得、ビルド時の外部アクセス、コンテナ実行時の外部アクセスは、それぞれ別の設定として確認する必要があります。
それでも直らない場合の追加確認
DNS とルールが正しくても、経路上のパケットサイズや TLS の扱いが原因でタイムアウトすることがあります。TUN を使っている場合は、仮想インターフェースがデフォルトルートを奪っているか、IPv6 の通信だけが別経路へ漏れていないかを確認します。IPv4 では成功し IPv6 だけ失敗する環境なら、いったん IPv6 を対象外にして再テストすると原因を絞れます。ただし恒久的に無効化する前に、ネットワーク管理者や利用環境の方針を確認してください。
MTU の問題は、DNS や小さな API リクエストでは気づきにくく、大きなレイヤー転送で表面化します。Wi-Fi、VPN、TUN、Docker の仮想ネットワークが何重にも重なる構成では、最小の変更から試します。Clash のログに接続リセットが出ている場合はノード変更と経路確認を先に行い、TLS 証明書エラーが出ている場合は証明書検査や企業プロキシの有無を確認します。エラーの種類が異なる問題を、同じルール追加で解決しようとしないことが大切です。
また、Docker Hub 側のレート制限やアカウント認証も確認対象です。プロキシ経由では複数の利用者が同じ出口 IP を共有するため、匿名リクエストの制限に達しやすいことがあります。ネットワーク接続が成功しているのに HTTP 429 や認証エラーが返る場合は、タイムアウト対策ではなく Docker Hub のログイン状態、トークン、利用制限を確認してください。
よくある質問
ブラウザが使えるのに、なぜ Docker だけ失敗しますか?
ブラウザは OS のシステムプロキシを自動利用できますが、Docker Engine は独立した daemon として動作し、同じ設定を参照しないことがあります。Docker Desktop の内部 VM や WSL が別の DNS・ルートを使う場合もあるため、ブラウザの成功は Docker の成功を保証しません。Clash のログと Docker 側の設定を同じ操作で確認してください。
TUN モードを常にオンにすれば解決しますか?
プロキシ設定を読まないプロセスを救える可能性はありますが、必ず解決するわけではありません。TUN は VPN、IPv6、DNS 拡張、他のネットワークフィルターと競合することがあります。まず明示的な Docker プロキシとルール分流を確認し、それで経路に乗らないプロセスがある場合に TUN を試すのが安全です。
Docker Hub のドメインをすべて PROXY にすべきですか?
すべてを無条件に PROXY へ送る必要はありません。認証、レジストリ、レイヤー配信のログを確認し、必要なホストだけを安定したグループへ送ります。社内レジストリや LAN 内のサービスを誤って迂回しないよう、プライベートアドレスや社内ドメインの DIRECT ルールを上位に置く設計も有効です。
大きなレイヤーだけ取得に失敗する場合はどうしますか?
ノードの混雑、CDN への経路、MTU、プロキシの転送制限、接続の再利用を順番に調べます。別ノードで同じイメージを試し、Clash のログでリセットや再接続が発生する時点を確認してください。HTTP 429 や認証エラーなら、ネットワーク経路ではなく Docker Hub の利用制限を調べる必要があります。
単純なシステムプロキシ設定だけに頼る方法は、Docker Engine や内部 VM、WSL のような別レイヤーで設定漏れが起きやすく、逆にすべての通信を強制する TUN だけの運用は VPN 競合や DNS の副作用を招くことがあります。Clash なら、ログで実際の Docker Hub ホストを確認し、ルール分流と明示的な Docker プロキシを組み合わせ、必要な場合だけ TUN を使うという段階的な構成にできます。原因を可視化しながら Docker の取得経路を整えたい場合は、次のダウンロードページから利用環境に合う Clash クライアントを確認してください。