1. ブラウザは通るのにコンテナだけ直結する理由
Windows で Clash のシステムプロキシや TUN が有効でも、Docker Desktop が起動する Linux コンテナは、ホスト OS のレジストリに書かれたプロキシ設定を自動では継承しません。コンテナは独自のルーティング表とブリッジ/オーバーレイネットワークを持ち、アプリは「プロキシなし」のまま外向きへ出ようとします。ブラウザや PowerShell の一部操作はホスト側で完結するため快適でも、docker exec 先の curl や apt、pip、社外向け API クライアントだけがタイムアウトする——という症状は、この名前空間の分離が典型原因です。
加えて、コンテナ内から見た 127.0.0.1 はコンテナ自身のループバックであり、ホストで待受している Clash とは別物です。ホストの 7890 を指したつもりが、実際には空振りしているケースが非常に多いです。解決の鍵は、Docker が提供する特殊名 host.docker.internal を経由してホストの IP に届けること、そして多くの CLI/HTTP クライアントが読む HTTP_PROXY 系を明示的に渡すことです。
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.yaml の mixed-port/port で確認してください。
重要なのは、待受が 127.0.0.1 のみにバインドされていると、host.docker.internal からの接続が届かない場合がある点です。コンテナからホストへ届けるには、0.0.0.0 で待つか、LAN 向けにポートを開け、Windows ファイアウォールでブロックされていないかを確認します。ミックスドポートを LAN に公開する手順や注意点は Windows 11 でのミックスドポートとファイアウォールの記事と整合させると理解しやすいです。
TUN モードだけに頼ると、コンテナ内プロセスがプロキシ環境変数なしで外向きへ出ようとして、期待と違う経路になることがあります。トラブル時は TUN とルーティングの切り分けも参照しつつ、本稿の明示プロキシと併用するのが実務では扱いやすいです。
4. HTTP_PROXY/HTTPS_PROXY/NO_PROXY の典型値
コンテナ内の多くのツールは、次の環境変数を参照します。
HTTP_PROXY/http_proxy:HTTP、および多くの HTTPS クライアント向けHTTPS_PROXY/https_proxy:HTTPS 向け(HTTP CONNECT を使う実装ではhttp://URL のままでよいことが多い)ALL_PROXY/all_proxy:SOCKS を使うツール向け(必要ならsocks5h://host.docker.internal:7891など)NO_PROXY/no_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=... と ARG/ENV を 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 hosts や nslookup を実行し、ホスト側の Clash ログのホスト名表示と突き合わせます。
逆に、プロキシ経由で名前解決したいツールは ALL_PROXY に socks5h:// を使うなど、ツール側の仕様に合わせた調整が必要になる場合があります。ここは「コンテナ × プロキシ × DNS」の三つ巴で、一度に直そうとせず、HTTP_PROXY を入れたうえでログを見るのが早いです。
9. 切り分け表
| 症状 | よくある原因 | 確認すること |
|---|---|---|
| ホストの curl は通るがコンテナは直結のまま | HTTP_PROXY がコンテナに渡っていない |
docker exec 先で env、Compose の environment |
connection refused on host.docker.internal:7890 |
Clash が 127.0.0.1 のみ待受、FW で遮断 |
待受アドレス、ミックスドポートと FW |
| イメージ pull だけ異常に遅い/失敗 | レジストリをプロキシに流しすぎ | NO_PROXY にレジストリホストを追加 |
| 社内 API だけタイムアウト | 社内ドメインがプロキシに向かっている | NO_PROXY、Clash ルールで DIRECT |
これでも原因が特定しにくいときは、Clash のログで該当接続が期待するノードに乗っているか、DIRECT になっていないかを確認すると、ルール側の修正に進みやすくなります。
10. まとめ
Windows で Clash が効いていても、Docker Desktop のコンテナは別ネットワークにいるため、システムプロキシを知らず直結しがちです。127.0.0.1 はコンテナ自身を指すので、ホストのプロキシへは host.docker.internal と実ポートを組み合わせ、HTTP_PROXY/HTTPS_PROXY で明示し、イメージ取得や社内向けは NO_PROXY で除外する——この流れをテンプレ化しておけば、docker run と Compose の両方で同じ考え方を適用できます。
クライアントによってはルール編集のしやすさやログの見やすさで差が出ます。長時間の開発や複数コンテナ運用では、YAML とログが追いやすい Clash 系クライアントのほうが運用しやすいと感じる人も多いでしょう。導入や更新の入口は 本サイトのダウンロードページから辿ると、OS ごとの選定も迷いにくくなります。