Windows ガイド 開発者向け タグ: Docker Desktop host.docker.internal HTTP_PROXY NO_PROXY

Docker Desktop のコンテナが Clash を通らない?Windows で host.docker.internal とプロキシ環境変数を揃える

Windows ではブラウザや Clash のシステムプロキシは効いているのに、docker runDocker Compose で起動したコンテナ内のアプリだけが直結してしまう——このズレは、コンテナが別のネットワーク名前空間にあり、ホストの 127.0.0.1 や Windows のプロキシ設定をそのまま引き継がないことが原因です。本稿では、コンテナからホスト上の Clash 待受へトラフィックを向ける host.docker.internalHTTP_PROXYHTTPS_PROXYNO_PROXY の典型値、イメージ取得や社内レジストリを例外にする考え方を、再現しやすいチェックリスト形式で整理します。

読了時間:約18分
Clash 編集部

1. ブラウザは通るのにコンテナだけ直結する理由

WindowsClash のシステムプロキシや TUN が有効でも、Docker Desktop が起動する Linux コンテナは、ホスト OS のレジストリに書かれたプロキシ設定を自動では継承しません。コンテナは独自のルーティング表とブリッジ/オーバーレイネットワークを持ち、アプリは「プロキシなし」のまま外向きへ出ようとします。ブラウザや PowerShell の一部操作はホスト側で完結するため快適でも、docker exec 先の curlaptpip、社外向け API クライアントだけがタイムアウトする——という症状は、この名前空間の分離が典型原因です。

加えて、コンテナ内から見た 127.0.0.1コンテナ自身のループバックであり、ホストで待受している Clash とは別物です。ホストの 7890 を指したつもりが、実際には空振りしているケースが非常に多いです。解決の鍵は、Docker が提供する特殊名 host.docker.internal を経由してホストの IP に届けること、そして多くの CLI/HTTP クライアントが読む HTTP_PROXY 系を明示的に渡すことです。

ヒント:全体のルール設計は Clash のドキュメントで押さえつつ、本記事は「Docker Desktop on Windows のコンテナから、ホスト上の Clash 待受へトラフィックを流す」ことに絞ります。WSL2 だけの話題は 別稿で扱っています。

2. Docker のネットワークと 127.0.0.1 の罠

Docker Desktop(Windows)は、Linux カーネルを VM 経由で動かし、その中でコンテナを起動します。コンテナのデフォルトはブリッジネットワークであり、デフォルトゲートウェイ越しにインターネットへ出ます。このときホストの 127.0.0.1 へは、上で述べたとおり直結しません

代わりに使うのが host.docker.internal です。名前解決され、ホストマシン側のサービスへ TCP で接続するためのエイリアスとして機能します(環境により host-gateway を明示する例もあります)。ここに Clashミックスドポートや HTTP プロキシポートをバインドさせ、コンテナからは http://host.docker.internal:7890 のように参照するのが基本パターンです。

動作確認として、プロキシをまだ設定していないコンテナで次を実行し、タイムアウトや接続拒否を確認したうえで、後述の環境変数を足して再試行すると切り分けが速くなります。

docker run --rm curlimages/curl:latest -sS -I https://www.google.com --max-time 15

3. ホスト側 Clash の待受をコンテナから届ける

以降の例では、よくある 7890ミックスドポートとして使う想定で書きます。実際の値は Clash の GUI か config.yamlmixed-portport で確認してください。

重要なのは、待受が 127.0.0.1 のみにバインドされていると、host.docker.internal からの接続が届かない場合がある点です。コンテナからホストへ届けるには、0.0.0.0 で待つか、LAN 向けにポートを開け、Windows ファイアウォールでブロックされていないかを確認します。ミックスドポートを LAN に公開する手順や注意点は Windows 11 でのミックスドポートとファイアウォールの記事と整合させると理解しやすいです。

TUN モードだけに頼ると、コンテナ内プロセスがプロキシ環境変数なしで外向きへ出ようとして、期待と違う経路になることがあります。トラブル時は TUN とルーティングの切り分けも参照しつつ、本稿の明示プロキシと併用するのが実務では扱いやすいです。

注意:LAN 全体にプロキシポートを開くと、同一ネットワークからの接続も受け付ける可能性があります。開発用マシン限定か、必要ならファイアウォールで送信元を絞ってください。

4. HTTP_PROXY/HTTPS_PROXY/NO_PROXY の典型値

コンテナ内の多くのツールは、次の環境変数を参照します。

  • HTTP_PROXYhttp_proxy:HTTP、および多くの HTTPS クライアント向け
  • HTTPS_PROXYhttps_proxy:HTTPS 向け(HTTP CONNECT を使う実装では http:// URL のままでよいことが多い)
  • ALL_PROXYall_proxy:SOCKS を使うツール向け(必要なら socks5h://host.docker.internal:7891 など)
  • NO_PROXYno_proxy:プロキシを使わないホスト/サフィックス(カンマ区切り)

大文字・小文字の両方をセットしておくと互換性が上がります。ホストの Clash へ向ける最小例は次のとおりです(ポートは環境に合わせて置換)。

HTTP_PROXY=http://host.docker.internal:7890
HTTPS_PROXY=http://host.docker.internal:7890
NO_PROXY=localhost,127.0.0.1,::1,host.docker.internal,.internal,.local

NO_PROXY には、社内レジストリプライベート Docker レジストリのホスト名、社内 API のドメイン、*.k8s.local のようなクラスタ内名を追加します。すべてをプロキシに流すと、イメージの pull が遅い・証明書エラーになる・ループする、といった副作用が出やすいです。

5. docker run で渡す

一回きりの試行なら -e で十分です。

docker run --rm -it \
  -e HTTP_PROXY=http://host.docker.internal:7890 \
  -e HTTPS_PROXY=http://host.docker.internal:7890 \
  -e NO_PROXY=localhost,127.0.0.1,::1,.internal \
  curlimages/curl:latest -sS -I https://www.google.com

ビルド時にプロキシが必要な場合は docker build --build-arg HTTP_PROXY=...ARGENV を Dockerfile に書くパターンもあります。企業ネットワークでは社内ミラーへ NO_PROXY を厚めにすることが多いです。

6. Docker Compose に書く

Docker Compose では、サービス単位で environment を定義するか、env_file でまとめて渡します。複数サービスで同じ値を使うなら x-env-proxy のような YAML アンカーや .env ファイルに HTTP_PROXY=... を置き、各サービスで environment: に展開する運用が読みやすいです。

services:
  app:
    image: your-image:tag
    environment:
      HTTP_PROXY: http://host.docker.internal:7890
      HTTPS_PROXY: http://host.docker.internal:7890
      NO_PROXY: localhost,127.0.0.1,::1,registry.internal,your-registry.local

Compose のバージョンやプラグインによっては、プロジェクト名やネットワーク別名を NO_PROXY に足す必要が出ます。コンテナ間通信だけを直結させたいサービス名を列挙するのも有効です。

7. Docker Desktop のプロキシ設定(任意)

Docker Desktop の Settings に、手動プロキシやシステムプロキシの利用設定があります。ここでホストのプロキシ URL を指定すると、デーモン側のイメージ pull などに効く一方、すべてのコンテナに自動で環境変数が注入されるわけではありません。挙動はバージョンで差があるため、再現性を重視するならコンテナ側の HTTP_PROXY を明示するほうが確実です。

「GUI で一度設定すれば全部行くはず」という期待はしばしば裏切られるので、本稿のチェックリストと併せて、実際にコンテナ内で env | grep -i proxy を叩いて確認する習慣をつけるとよいでしょう。

8. DNS と名前解決の落とし穴

コンテナは組み込み DNS リゾルバ経由で名前解決します。Clash の Fake-IP やスプリット DNS をホストだけで運用している場合、コンテナ内の解決結果がホストと異なり、プロキシに乗るべきホストが DIRECT 側に落ちることがあります。症状がドメイン依存で現れるときは、コンテナ内で getent hostsnslookup を実行し、ホスト側の Clash ログのホスト名表示と突き合わせます。

逆に、プロキシ経由で名前解決したいツールは ALL_PROXYsocks5h:// を使うなど、ツール側の仕様に合わせた調整が必要になる場合があります。ここは「コンテナ × プロキシ × DNS」の三つ巴で、一度に直そうとせず、HTTP_PROXY を入れたうえでログを見るのが早いです。

9. 切り分け表

症状 よくある原因 確認すること
ホストの curl は通るがコンテナは直結のまま HTTP_PROXY がコンテナに渡っていない docker exec 先で env、Compose の environment
connection refused on host.docker.internal:7890 Clash127.0.0.1 のみ待受、FW で遮断 待受アドレス、ミックスドポートと FW
イメージ pull だけ異常に遅い/失敗 レジストリをプロキシに流しすぎ NO_PROXY にレジストリホストを追加
社内 API だけタイムアウト 社内ドメインがプロキシに向かっている NO_PROXYClash ルールで DIRECT

これでも原因が特定しにくいときは、Clash のログで該当接続が期待するノードに乗っているか、DIRECT になっていないかを確認すると、ルール側の修正に進みやすくなります。

10. まとめ

WindowsClash が効いていても、Docker Desktop のコンテナは別ネットワークにいるため、システムプロキシを知らず直結しがちです。127.0.0.1 はコンテナ自身を指すので、ホストのプロキシへは host.docker.internal と実ポートを組み合わせ、HTTP_PROXYHTTPS_PROXY で明示し、イメージ取得や社内向けは NO_PROXY で除外する——この流れをテンプレ化しておけば、docker runCompose の両方で同じ考え方を適用できます。

クライアントによってはルール編集のしやすさやログの見やすさで差が出ます。長時間の開発や複数コンテナ運用では、YAML とログが追いやすい Clash 系クライアントのほうが運用しやすいと感じる人も多いでしょう。導入や更新の入口は 本サイトのダウンロードページから辿ると、OS ごとの選定も迷いにくくなります。

Clash を無料ダウンロードして、ホストとコンテナの両方で出口を揃える