開発環境 / Docker · · 読了まで約 18 分

Docker コンテナをホストの Clash 経由にする:HTTP プロキシ環境変数とゲートウェイ方式の比較(2026)

ローカル開発や CI のジョブで、コンテナの中から git clonenpm installpip など外向きの HTTP(S) が必要になる場面はよくあります。いちいちコンテナ内に別のプロキシクライアントを入れるのは運用が重いので、すでにホストで動いている Clash の HTTP リスナー(多くの構成では mixed-port や専用の port)へ、HTTP_PROXY 系の環境変数で向ける方法が現実的です。本稿ではその具体例に加え、Linux でブリッジ越しにホストへ届けるアドレスの決め方デフォルトゲートウェイをホストに寄せる考え方(上級者向け)、そしてdocker pull のように Docker デーモン側が扱う通信との違いまでを、実務で迷いやすい点とともに整理します。

1. 何を解決したいか:コンテナ出口とホスト Clash の関係

Docker のデフォルト構成では、コンテナはブリッジネットワーク上の別 IP 空間に置かれ、ホストのループバック(127.0.0.1)は「コンテナ自身」のループバックであり、ホストで 127.0.0.1:7890 を開いていても、コンテナ内の 127.0.0.1:7890 には届きません。ここを取り違えると「プロキシを指定したのに繋がらない」という状態に陥りがちです。目的はシンプルで、コンテナ内プロセスが発行する TCP 接続のうち、プロキシ対応のものをホストの Clash の HTTP プロキシポートへ送ることです。HTTPS も、多くのツールは CONNECT トンネルでプロキシを経由します。

本稿が扱うのはあくまで開発・検証用途の典型的なパターンです。組織のセキュリティポリシーや契約上、プロキシやトンネルの利用が制限されている環境では、手順を真似する前に許諾とガバナンスを確認してください。また、Clash の購読やルールの基礎は サブスクリプション導入ガイドと、出口やドメインの振り分けは ルールルーティングの解説とあわせて読むと、コンテナから出たトラフィックがどの策略に乗るかもイメージしやすくなります。

2. ホスト側の前提:HTTP ポートと allow-lan

Clash / mihomo 系では、しばしばmixed-portに HTTP と SOCKS が同居する構成が使われます。設定ファイルの実際のキー名やデフォルト値はビルドやテンプレートで異なるため、ダッシュボードまたは設定 YAML で「どのポートが HTTP プロキシとして応答しているか」を必ず確認してください。以降の例では説明のため 7890 を仮置きしますが、環境に合わせて読み替えが必要です。

コンテナはホストから見ると別ホストのような扱いになるため、Clash が 127.0.0.1 のみにバインドしていると外部から届きません。LAN からの接続を受け付ける設定(例:allow-lanを有効にし、バインドアドレスを環境に応じて調整する必要があります。ここを開くと同一 L2 上の他マシンからもそのポートに届く可能性があるため、ノート PC をカフェの共有 Wi‑Fi に繋いだまま広く開く、といった運用は避け、必要最小限の範囲に留めるのが安全です。

3. 方式 A:HTTP_PROXY / HTTPS_PROXY / NO_PROXY

多くの CLI ツールと言語ランタイムは、大文字または小文字の HTTP_PROXY / HTTPS_PROXYを参照します。HTTPS_PROXY が未設定のとき HTTP_PROXY にフォールバックする実装もあります。形式は通常 http://ホスト:ポート で足り、Clash 側が HTTP プロキシとして CONNECT を処理できることが前提です。

NO_PROXY(または no_proxyは、社内レジストリやローカルの *.local、Kubernetes のサービス名などプロキシを通すべきでない宛先を列挙するために重要です。ここが空だと、本来直結したい私有リポジトリまでプロキシに流れて失敗する、という事故が起きます。カンマ区切りのホスト名や IP、先頭ドット付きサフィックスなど、利用ツールが解釈する形式に合わせてください。

# Example: one-off docker run (host address is placeholder)
docker run --rm -e HTTP_PROXY=http://HOST_IP:7890 \
  -e HTTPS_PROXY=http://HOST_IP:7890 \
  -e NO_PROXY=localhost,127.0.0.1,::1 \
  alpine sh -lc 'wget -qO- https://example.com -O /dev/null && echo ok'

実際の HOST_IP は次節のとおり OS と Docker の組み合わせで変わります。IPv6 だけ有効な環境では NO_PROXY::1 を入れるか、プロキシ URL を IPv4 に固定するなど、スタック全体で一貫させる必要があります。

4. コンテナから「ホスト」を指すアドレス

Docker Desktop(macOS / Windows)では、特別な DNS 名 host.docker.internal がホストを指すことが多く、http://host.docker.internal:7890 のように書けると手早いです。ただしLinux のネイティブ Docker ではこの名前が無い、または挙動が異なる場合があるため、依存しすぎない方がよいです。

Linux ネイティブでは、コンテナが接続する「ホスト側の IP」はdocker0 ブリッジのゲートウェイ(多くの環境で 172.17.0.1)だったり、user-defined bridge のブリッジ IP の先頭だったりします。確実に取りたいときは、一時コンテナで ip route を見て default の次ホップを確認する、ホスト側で docker network inspect bridge して Gateway を読む、といった方法があります。固定したい場合は --add-host で名前を割り当てる手もあります。

# Example: inspect default bridge gateway on Linux host
docker network inspect bridge --format '{{(index .IPAM.Config 0).Gateway}}'

WSL2 の内側から Docker を動かしている場合は、「コンテナから見たホスト」が Windows 側なのか WSL2 の仮想 NIC なのかで迷子になりやすいです。症状が変わるたびに、実際にコンテナ内から curl -v でどこに SYN が飛んでいるかを確認するのが近道です。

5. Docker Compose とビルド時(BuildKit)

Compose では environment: に同じ変数を並べるほか、複数サービスで共通なら x- 拡張や env_fileに寄せると重複管理が楽になります。ビルド段階で aptnpm ci を走らせる Dockerfile では、docker compose build のコンテキストにプロキシが渡るかが別問題です。BuildKit 有効時は DOCKER_BUILDKIT=1 とあわせ、build.argsHTTP_PROXY を Dockerfile の ARG に渡すパターンが一般的です。

CI(GitHub Actions など)では、ランナー上に Clash を常駐させるより、そもそもプロキシ不要なネットワークにジョブを載せ替える方が安定していることが多いです。どうしてもプロキシが要る場合でも、シークレットをイメージに焼かないよう、環境変数の渡し方とログマスキングに注意してください。

6. 方式 B:ゲートウェイをホストに寄せる(透明性の高い経路)

環境変数を解釈しないバイナリや、UDP・任意の TCP を含むプロキシ非対応の通信までまとめてホスト側のスタックに載せたい場合、コンテナのデフォルトルートをホストに向け、ホストで NAT や TUN 系のクライアントが捕捉するという発想に移ります。これはiptables / nftables・IP フォワーディング・ルーティングなど、OS ネットワークの理解が求められる上級構成です。ミスするとコンテナだけ孤立したり、意図せず広い範囲を NAT してしまったりするため、本稿では詳細な手順よりも「HTTP_PROXY で足りるならそちらを第一選択とする」という位置づけに留めます。

ホストで Clash の TUN モードを使い、そこにコンテナ_subnet のトラフィックを誘導する、という構成も理論上は可能ですが、Docker のブリッジと TUN の優先順位・DNS の所在が絡み、トラブル時の切り分けコストが跳ね上がりがちです。TUN の一般的な考え方は TUN モードの解説を参照しつつ、Docker との併用は小さな実験環境で検証してから本番開発フローに載せるのが無難です。

7. docker pull は別物:デーモンのプロキシ設定

docker run 時の環境変数はあくまでコンテナ内プロセスに効きます。一方 docker pullDocker デーモンがレジストリへ接続するため、ホストのシェルに export HTTP_PROXY=... しただけでは効かないことがあります。Linux では systemd のユニットドロップインで Environment=HTTP_PROXY=...docker.service に渡す、/etc/docker/daemon.json にプロキシ関連の設定を書く(サポート状況はディストリとバージョンで要確認)、といったデーモン側の設定が別途必要です。

この点は当サイトの TUN モードの解説でも触れているとおり、「GUI プロキシがオンでも docker pull が遅い」の典型原因のひとつです。イメージ取得とアプリ依存解決を同一の頭で考えず、レイヤを分けて設定すると混乱が減ります。ホストで Clash を systemd 管理している場合の具体例は Ubuntu に Clash Meta を入れ systemd で運用する記事とも補完関係にあります。

8. 切り分け:接続拒否・DNS・証明書

まずコンテナ内で curl -v http://HOST:7890 のようにプロキシポートへ TCP が張れるかを見ます。ここで即拒否されるなら、バインドアドレス・ファイアウォール・allow-lan のいずれかが疑わしいです。TCP は張れるが HTTPS が失敗する場合は、プロキシ経由の CONNECT がルールで弾かれていないか、Clash のログにエラーが出ていないかを確認します。

企業プロキシのような中間者証明書を別経路で入れている環境では、コンテナイメージの CA ストアにそのルートが無く TLS が失敗することがあります。Clash 自体の話からは外れますが、「プロキシは通っているのに証明書エラー」はこの系統を疑うと早いです。逆に、DNS だけがコンテナ内で異なるリゾルバを見ており、意図しない IP に繋いでいるケースでは、NO_PROXY やコンテナの /etc/resolv.conf、Docker の DNS 設定を点検します。

9. まとめ

開発用コンテナをホストの Clash に寄せる場合、第一選択は HTTP_PROXY 系でホストの HTTP プロキシポートを明示することです。ホスト IP の取り方は Docker Desktop と Linux で異なるため、毎回コンテナから実測で確認する癖を付けると長期的に楽です。NO_PROXY を適切に整え、docker pull のようにデーモンが担う通信は別設定だと心得ておけば、トラブル時の当たり所も明確になります。ゲートウェイ寄せや TUN 併用は強力ですが、複雑さと運用コストが跳ねるので、必要になった段階で検討するのがよいでしょう。

Clash 系クライアントは実装が分かれていても、ルールと購読という考え方は共通です。コンテナから出る HTTP(S) がどの策略・どのノードに乗るかは、結局ホスト側の設定の質に依存します。同カテゴリのツールと比べても、ルール表現と可観測性のバランスが取りやすい点は、開発者にとって長時間の作業を支える利点になります。

まずは手元の OS に合うビルドを選び、ホストでポートと LAN 受け入れを整えたうえでコンテナから試すのが最短です。パッケージの入手と各プラットフォーム向け一覧は → 無料で Clash をダウンロードして、快適な接続を試す からどうぞ。

トピックの近さで選んだ関連記事 — 同じカテゴリの Clash 実践ガイド。