症状の整理:Pulling のまま/TLS で止まるときに疑うこと
コンテナ開発で一番ストレスが溜まりやすいのが、docker pull がレイヤ転送に進まず、進捗表示が長時間「Pulling fs layer」のまま変わらないパターンです。ログやコンソールには TLS handshake timeout、i/o timeout、connection reset のような文言が混じり、ビルドパイプラインや CI でも同様に詰まります。
ここで誤解しやすいのは、「ブラウザで Docker Hub のサイトが開ける=イメージ取得も問題ない」という短絡です。マニフェスト取得・認証・実レイヤの CDNは別ホストや別経路に割られることがあり、どこか一段だけプロキシや安定した出口に乗っていないと、TLS のハンドシェイクや大きめの転送でタイムアウトが表面化します。
ユーザーの検索意図としては、「ミラー設定をいじる前に、手元のネットワークと開発マシン側で確実にプロキシへ流れる経路を作りたい」というものが多いです。本記事では Clash の TUN モードを軸に、段階的に切り分けて通す手順をまとめます。
システムプロキシや環境変数だけでは足りないことがある理由
Docker Desktop を使う場合、設定画面に HTTP/HTTPS プロキシを書けることがあります。Linux のネイティブ Docker では /etc/systemd/system/docker.service.d/ に HTTP_PROXY を足す、といった運用もよく見られます。これらは一定の場面で有効ですが、次のような抜け道が残りがちです。
- デーモンと CLI のプロセス境界:
dockerコマンド自体とdockerdは別です。どちらに変数が効くかはディストリビューションや rootless 構成で変わります。 - 名前解決と実接続のズレ:DNS がローカルキャッシュや別リゾルバを見て、TLS の SNI と実ルーティングが期待とずれることがあります。
- 複数ホストへの縦割りアクセス:
registry-1.docker.io、auth.docker.io、CDN ドメインなど、すべてが同一の「ブラウザと同じ経路」とは限りません。
Clash の TUN(仮想 NIC)は、HTTP プロキシを「読むアプリ」と「読まないデーモン」を個別に説教する代わりに、TCP/UDP フローを OS の出口付近で一度ルールエンジンへ集約する発想です。そのため「ブラウザでは見えていたプロキシ設定」と同じテーブルに docker の外向き通信も載せやすいのが実務上のメリットです。
用語メモ:TLS handshake timeout は「鍵交換の往復が規定時間内に終わらなかった」という現象で、輻輳・パケットロス・誤った経路・MITM 検査の干渉など、原因は一つに決め打ちできません。だからこそ実際にどのホストへどのポリシーが当たったかをログで見るのが早いです。
TUN を触る前の準備(プロフィールと競合)
手順に入る前に次を確認してください。
- 購読プロフィールが有効で、ノードの遅延テストが妥当な値になっていること。
- 別ベンダーの常駐 VPNや古い仮想アダプタがルートを握っていないこと。検証中は止めると切り分けが速いです。
- 社内ポリシーで全トラフィックのミドルボックスが禁止されていないこと。仕事用端末では IT ガイドラインを優先してください。
ステップ 1〜3:TUN を有効にする(管理者権限まで含む)
GUI は製品ごとに文言が違いますが、多くのデスクトップ Clash クライアントで共通する流れは次のとおりです。
- 正しい YAML を選択・適用する。空プロフィールのまま TUN をオンにしても意味がありません。
- Windows の UAC/macOS のネットワーク拡張の許可を済ませる。途中でキャンセルすると仮想 NIC が立ちません。
- TUN のトグルをオンにし、接続ログパネルを開いたままにする。
TUN とシステムプロキシを同時にオンにする初期セットアップは避ける:両方が効いていると「どちらが効いたか」ログの読み取りが難しくなります。まずは TUN だけで docker を試し、通ったら必要に応じて併用を検討するのが無難です。
ステップ 4:Docker Hub まわりでよく出るホスト(ルール確認の勘所)
厳密な一覧は時期により変わりますが、トラブル時にログへ並びやすいのは次のような名前です。
registry-1.docker.io(マニフェスト/メタデータ)auth.docker.io(認証)- CDN/クラウドフロント系のホスト(レイヤの実体転送)
Clash の接続一覧で、これらが意図したプロキシグループに振られているか、誤って DIRECT になっていないかを見ます。国内/海外スプリット構成では、海外レジストリだけが狭い直通ルールに捕まって不安定出口へ落ちているケースがよくあります。
ステップ 5:docker pull での実地確認
まずはレイヤがごく薄い公式イメージで試します。
docker pull alpine:latest
これでも進まない場合は、Docker Desktop の「Restart」やデーモン再起動のうえ、もう一度ログを観察してください。同じコマンドでも途中で別ホストへ切り替わるため、接続ログはスクロールしながら複数行を見る必要があります。
Linux で systemd を使う場合、プロキシ環境変数と TUN を二重に噛ませていると挙動が読みにくくなるので、切り分けのときはどちらか一方に寄せると原因が見えやすくなります。
DNS と fake-ip:名前は通っても経路がズレるとき
TUN がオンでも、名前解決の応答とルール評価の順序が噛み合わないと、「ヒットしたルールが思ったものと違う」ように見えます。Mihomo 系プロフィールでは dns.enhanced-mode が fake-ip のとき、アプリ側の挙動とセットで説明されることが多いので、購読元の README もあわせて読む価値があります。
- 国内ミラーだけ DIRECT にしたい場合は、ミラー側ドメインを明示ルールで先に置く。
- Docker が別 DNS を参照していないか(企業プロファイルや
daemon.jsonの DNS 指定)を確認する。 - IPv6 が別経路になっていないか、問題が再現するときだけ一時的に比較する。
Docker Desktop(macOS / Windows)とネイティブ Linux の差異メモ
Docker Desktop は軽量 VM/内部ブリッジを挟むため、ホスト側で TUN をオンにした効き方が「ホストのプロセスだけ見える」ときと「VM 境界まで届く」ときで体感が変わります。いずれの場合もホストの外向きが安定したプロキシ経由になることが先で、そのうえで Desktop 設定のプロキシ欄と整合させます。
ネイティブ Linux では、前述のとおりデーモンの systemd ドロップインと TUN の効き方がディストリビューション依存です。ログで実ホストとポートが見える状態を作ってから設定をいじると、試行錯誤の回数が減ります。
それでもダメなときのチェックリスト
- TUN はオンだがログが増えない → ほかの VPN が同レイヤーを占有している可能性。
- すべて DIRECT →
MATCHより上に広すぎる直通ルールが無いか確認。 - ANTIVIRUS の HTTPS 検査が TLS を壊していないか別軸で確認。
- 企業プロキシの証明書を OS または Docker に信頼させる必要が無いか(環境依存)。
よくある質問
ブラウザは問題ないのに pull だけ失敗するのはなぜ?
ブラウザと Docker Engine は別プロセスであり、参照するプロキシ情報も異なります。レジストリ関連ホストへの TLS がどこかで不安定になると、ブラウザでは表面化しないタイミングで docker pull が落ちます。
ミラー設定は必要?
地域や回線によってはミラーが最速です。本記事は出口を Clash で明示的にプロキシへ載せることにフォーカスしています。ミラーと併用して問題ありません。
CI で同じ症状が出る
Runner が別マシンなら TUN は当てはまりません。その場合は Runner 側のプロキシ、ミラー、またはオフラインキャッシュの設計へ移ります。手元で再現するなら本稿の手順が参考になります。
単体の HTTP プロキシツールと比べた Clash系の強み
環境変数だけでごまかす運用は、単一プロジェクトでは速い一方、次のような摩擦が出やすいです。
- GUI IDE から開いたターミナルに変数が無いといった再現性の低さ。
- UDP や複数ホストへの縦割り通信で設定が追いつかないこと。
- 国内外スプリットを手書きで保守するコスト。
Mihomo コアを載せた Clash クライアントは、購読プロフィールをそのままルールテーブルとして使い、TUN で docker を含む外向き TLS を一つのダッシュボードで観測できるのが利点です。個別ツールを増やして設定ファイルがバラバラになるより、接続ログで命中ルールを追える一式にまとめておくと、コンテナ開発まわりのネットワーク詰まりがだいぶ楽になります。
OS ごとに配布物が分散しがちなので、公式サイトで整理されたパッケージから入手しておくとバージョン管理もしやすいです。