はじめに
Docker Hub からコンテナイメージを取得しようとした際に、docker pull が途中で止まる、接続がタイムアウトする、または i/o timeout や context deadline exceeded が表示されることがあります。ブラウザーでは通常どおりウェブサイトを開けるのに、Docker だけが失敗する場合は、Docker デーモンの通信経路と通常のアプリケーション通信が異なっている可能性があります。
Docker CLI はコマンドを実行するユーザーのプロセスだけでなく、バックグラウンドで動作する Docker デーモンを通じてレジストリへ接続します。そのため、Clash のシステムプロキシをオンにしただけでは、Docker Hub の通信が自動的にプロキシへ流れるとは限りません。本記事では、Clash を利用して Docker Hub への通信を安定させるため、透過プロキシ、daemon.json、分流ルール、DNS、TLS、ログ確認を順番に整理します。
この記事の目的
Docker Hub の認証、マニフェスト取得、レイヤーダウンロードを適切な経路へ振り分け、原因をログから切り分けられる状態を作ります。
1Docker Hub だけが失敗する理由
Docker Hub の取得処理では、単一の URL に接続して終わるわけではありません。まず registry-1.docker.io にアクセスして認証情報を取得し、その後にイメージのマニフェストや各レイヤーを別の配信基盤から取得します。この複数段階の通信の一部だけが DIRECT になると、ブラウザーの動作とは異なる結果になります。
- Docker デーモンがプロキシを認識していない: Clash Verge Rev の System Proxy は、主にユーザーアプリケーション向けの設定です。systemd で起動した Docker は、その環境変数を継承しない場合があります。
- DNS の経路が一致していない: ドメインは解決できても、返されたアドレスへの接続が失敗することがあります。特に IPv6 と IPv4 の優先順位が異なる環境では、接続待ちが長くなります。
- 分流ルールが不足している: 認証用ドメインだけをプロキシに送り、実際のレイヤー配信先を DIRECT にすると、pull の途中で停止します。
- TLS 検証を誤って変更している: 証明書エラーを解決するために検証を無効化するのは危険です。時刻、CA 証明書、プロキシの TLS 設定を先に確認してください。
重要な注意
プロキシを利用する場合も、Docker Hub の利用規約、社内ポリシー、契約中のネットワークサービスの規約を確認してください。出所の不明な証明書をシステムへ追加したり、TLS 検証を無効化したりする方法は推奨しません。
2Clash 側の準備と透過プロキシ
最初に Clash のコアが起動しており、使用するプロキシグループに通信可能なノードが選択されていることを確認します。Docker を同じホスト上で動かしている場合、最も扱いやすい構成は、Docker デーモンから Clash の HTTP または SOCKS ポートへ明示的に接続させる方法です。一方、コンテナ内部の通信や複数サービスをまとめて処理したい場合は、Mihomo の TUN モードなどの透過プロキシを検討できます。
明示的プロキシと TUN モードの違い
| 方式 | 適している環境 | メリット | 注意点 |
|---|---|---|---|
| HTTP プロキシ | Docker デーモン単体 | 設定が明確で診断しやすい | デーモンの環境設定が必要 |
| SOCKS5 | 複数の TCP アプリケーション | 対応範囲が広い | Docker のバージョンや設定方法を確認する必要がある |
| TUN 透過プロキシ | ホスト全体・コンテナ通信 | アプリごとの設定を減らせる | ルーティング、権限、DNS の設計が複雑 |
まずは HTTP プロキシを使った明示的な設定で疎通を確認し、必要に応じて TUN へ移行するのが安全です。TUN を有効にする場合は、Clash が Docker ブリッジのアドレスやループバック経由の通信を誤って再度 TUN に送らないよう、除外ルートを確認します。Linux では管理者権限、Windows では Wintun などの仮想ネットワークドライバーが必要になることがあります。
3実際に daemon.json と systemd を設定する
ここが最も重要な作業です。Docker デーモンが Clash の HTTP プロキシを使用するように設定します。Clash の混合ポートが 7890、同じホストのループバックアドレスから利用できると仮定します。Docker Desktop を使っている場合は、Linux の systemd 設定ではなく、Docker Desktop の設定画面にある Resources や Proxies の項目を使用してください。
既存の daemon.json がある場合は、内容を消さずに JSON として統合してください。コメント、末尾の余分なカンマ、同じキーの重複があると Docker が起動できません。プロキシがホストのループバックではなく別コンテナや別ホストにある場合は、127.0.0.1 をその到達可能な IP アドレスへ置き換えます。
ファイルを保存したら、まず JSON の構文を確認し、その後に Docker を再起動します。
Docker のバージョンやディストリビューションによっては、プロキシ設定を systemd のドロップインで指定する構成も利用できます。その場合は以下のように専用ディレクトリを作成し、サービス環境へ変数を渡します。
設定後の確認
docker info を実行し、出力に HTTP Proxy、HTTPS Proxy が表示されるか確認します。表示されない場合は、設定ファイルの場所、JSON のキー名、systemd の読み込み状態を見直してください。
4分流ルールと DNS を整える
Docker Hub の通信を安定させるには、認証、API、配信の各ドメインを同じ方針で扱う必要があります。使用しているルールセットによって記法は異なりますが、手動で追加する場合は次のようなルールを参考にしてください。プロキシグループ名は、実際の設定に存在する名前へ変更します。
ただし、Docker Hub が返すレイヤー配信先は固定とは限りません。上記を設定しても途中で失敗する場合は、Clash の接続ログに表示される実際のホスト名を確認し、必要な範囲でルールを追加します。広すぎる DOMAIN-KEYWORD,docker は便利ですが、無関係なサービスまでプロキシへ送る可能性があるため、まずはドメインサフィックスを優先してください。
DNS 設定の確認
DNS は Clash と Docker の間で二重に処理されることがあります。ホスト側で名前解決を行い、Clash 側でも別の名前解決を行う構成では、結果が一致しない場合があります。Mihomo を使用する場合の一例は次のとおりです。
fake-ip は多くの TCP 通信で便利ですが、環境によっては Docker ブリッジ、ローカルレジストリ、特定の開発ツールとの相性問題が起きます。その場合は fake-ip-filter に内部ドメインを追加するか、検証目的で redir-host に切り替えて挙動を比較してください。設定を変更した後は Clash の DNS キャッシュを消去し、Docker デーモンを再起動すると結果を判定しやすくなります。
5動作確認とログからの切り分け
設定を変更したら、いきなり大きなイメージを取得するのではなく、段階的に確認します。まず Clash のログ画面を開き、次のコマンドを実行してください。
hello-world や alpine は比較的小さいため、認証と基本的なレイヤー取得のテストに向いています。ログに registry-1.docker.io、auth.docker.io、配信先のドメインが表示され、指定した Docker グループを通過していれば、Clash と Docker デーモンの連携は機能しています。
| 表示されるエラー | 主な原因 | 確認する場所 |
|---|---|---|
i/o timeout |
経路、ノード、DNS、ファイアウォール | Clash 接続ログ、ポート、ルーティング |
no such host |
DNS 解決の失敗 | Clash DNS、ホストの resolv.conf |
x509: certificate |
時刻、CA、TLS インスペクション | システム時刻、証明書チェーン |
401 Unauthorized |
認証情報またはレジストリ設定 | docker login、認証ドメイン |
connection refused |
Clash ポートが待ち受けていない | Clash の mixed-port、listen 設定 |
Linux では Docker サービスのログも確認できます。
curl が成功しても、Docker が成功するとは限りません。curl はユーザー環境のプロキシ変数を使い、Docker はデーモン設定を使うためです。両者を分けて検証することが、今回の問題を短時間で特定するポイントです。
6よくある設定ミスと安定運用
Docker Hub の取得が一度成功しても、ノード切り替えや Clash のアップデート後に再び失敗することがあります。設定を安定させるため、次の項目を定期的に確認してください。
- プロキシポートの取り違え: HTTP、SOCKS、Mixed のポート番号は同じとは限りません。
http://とsocks5://のスキームも実際のポートに合わせます。 - Docker コンテナ内の localhost を使用する: コンテナ内の
127.0.0.1はホストではありません。コンテナから Clash へ接続する場合は、ホストゲートウェイや到達可能な LAN アドレスを設計します。 - 認証だけを確認して安心する:
docker loginが成功しても、レイヤー配信先が別ルールで DIRECT なら pull は失敗します。 - 無制限にリトライする: ノードや DNS に問題がある状態で何度も再試行すると、原因が見えにくくなります。ログを保存してから一項目ずつ変更してください。
- TLS エラーを無視する:
insecure-registriesは信頼できる内部レジストリなど限定的な用途にのみ使用し、Docker Hub に対して安易に適用しないでください。
運用のコツ
本番環境では、Docker Hub の直接取得に依存せず、必要なイメージを社内のプライベートレジストリやミラーへ同期する方法も検討してください。可用性、監査、レート制限への対策をまとめて改善できます。
よくある質問
Clash の System Proxy をオンにすれば Docker も動きますか?
必ずしも動きません。System Proxy はログイン中のユーザーアプリケーションへ適用される設定であり、systemd が起動する Docker デーモンへ自動的に引き継がれないことがあります。Linux では daemon.json または systemd のサービス設定を明示的に確認してください。
TUN モードと daemon.json は同時に使えますか?
技術的には可能ですが、同じ通信が二重にプロキシ処理されると、ループ、遅延、TLS エラーの原因になる場合があります。最初はどちらか一方で疎通を確認し、併用する場合は no-proxy、TUN のルート、DNS の除外設定を慎重に設計してください。
x509 エラーが出た場合、証明書検証を無効にしてもよいですか?
Docker Hub に対しては推奨しません。まずシステム時刻、ルート CA、企業ネットワークの TLS インスペクション、Clash の証明書関連設定を確認します。信頼できる管理者が運用する内部レジストリ以外では、検証無効化を恒常的な解決策にしないでください。
小さいイメージは取得できますが、大きいイメージだけ失敗します。
ノードの帯域、接続維持時間、MTU、レイヤー配信先の分流が疑われます。複数のノードで比較し、Clash のログでレイヤー取得中に接続先が変わっていないか確認してください。Docker の再試行だけに頼らず、安定したノードや社内ミラーを利用する方が実運用では安全です。