目次
まずタイムアウトが Docker、ビルド、起動済みコンテナのどこで発生しているかを特定する
VS Code Dev Containers から Clash を利用する設定は、プロキシアドレスを一つ入力するだけでは完了しません。ベースイメージの取得、Dockerfile の実行、コンテナ内の Git、リモート拡張機能のダウンロードは、それぞれ異なるプロセスから開始されます。
「Dev Containers」の出力から失敗したコマンドの段階を特定し、その処理を行うプロセスへプロキシを渡します。そうしなければ containerEnv をどれほど詳しく記述しても、まだ作成されていないコンテナの問題は修正できません。
四つのネットワーク箇所
| 失敗した操作 | 実際にリクエストを送るコンポーネント | 設定箇所 |
|---|---|---|
| docker pull / ベースイメージの取得 | Docker daemon | Docker Desktop または daemon のプロキシ |
| Dockerfile RUN apt/npm | イメージのビルド段階 | build args または BuildKit の設定 |
| コンテナ内の curl/Git/pip | 実行中のコンテナ | containerEnv、remoteEnv、またはツールの設定 |
| VS Code リモート拡張機能のダウンロード | Dev Containers のリモートサービス | コンテナ環境と各拡張機能によるネットワークリクエスト |
エラーが「Starting Dev Container」より前に出る場合、コンテナがまだ実行されていないため、通常は .devcontainer/devcontainer.json の containerEnv では修正できません。まず失敗したコマンドと、VS Code の出力パネルに表示された段階を記録してください。
- VS Code のホスト拡張機能の取得と Docker の起動を担当する
- Docker のビルド段階build args または Docker のプロキシ設定を読み込む
- 実行中のコンテナcontainerEnv を読み込む
- リモート拡張機能とターミナルremoteEnv またはツール固有の設定を読み込む
失敗した段階にだけプロキシを設定します。ホスト、ビルド段階、コンテナの実行環境を同じ環境変数として扱わないでください。
コンテナ内の 127.0.0.1 はホストを指さない
Clash がホスト上で動作している場合、コンテナ内の http://127.0.0.1:7890 はコンテナ自身を指します。Windows と macOS の Docker Desktop では host.docker.internal を利用できます。Linux Docker では host-gateway を使い、同じ名前を割り当てられます。
Clash がホストのループバックアドレスだけを待ち受けている場合、コンテナから接続できないことがあります。ローカルネットワークからの接続を許可するか、mixed-port をコンテナから到達できるインターフェースで待ち受ける場合は、同時にシステムのファイアウォールで接続元を制限してください。7890 をインターネットへ直接公開してはいけません。
CLASH_HOST=host.docker.internal
CLASH_PORT=7890
getent hosts "$CLASH_HOST" || true
curl -v -x "http://$CLASH_HOST:$CLASH_PORT" https://www.example.com/
# Linux Docker 临时测试
docker run --rm --add-host=host.docker.internal:host-gateway curlimages/curl:latest -v -x http://host.docker.internal:7890 https://www.example.com/Linux ホストでは host-gateway を devcontainer.json に記述する
{
"runArgs": [
"--add-host=host.docker.internal:host-gateway"
]
}変更後に Dev Containers: Rebuild Container を実行します。以前のコンテナには、新しい hosts マッピングが自動では反映されません。
Docker Compose プロジェクトでは、サービスの下に extra_hosts: ["host.docker.internal:host-gateway"] を設定します。二か所へ重複して追加しないでください。
ポートへ到達できることを確認してから、実行中のコンテナにプロキシを設定する
前の手順は、curl が HTTP レスポンスを受け取って初めて成功と判断できます。次に、同じアドレスをコンテナ内のターミナルと VS Code のリモートプロセスへ渡します。mixed-port が 7890 でない場合は、以下の三か所のポートをすべて変更してください。
{
"containerEnv": {
"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"
},
"remoteEnv": {
"HTTP_PROXY": "${containerEnv:HTTP_PROXY}",
"HTTPS_PROXY": "${containerEnv:HTTPS_PROXY}",
"NO_PROXY": "${containerEnv:NO_PROXY}"
}
}HTTPS_PROXY が http:// で始まるのは通常正しい設定です。これは HTTP CONNECT プロキシ経由で HTTPS へアクセスすることを示し、プロキシポート自体を HTTPS に変えるわけではありません。NO_PROXY には Compose のサービス名、社内ネットワーク、ローカル開発用ドメインも追加してください。そうしないと、コンテナからデータベースや API へアクセスする通信まで Clash を経由することがあります。
保存後に Rebuild Container を実行し、新しいターミナルで env | grep -i proxy を実行します。起動済みのターミナルプロセスには、remoteEnv の変更が自動では反映されません。
イメージの取得と Dockerfile のビルドは個別に設定する
FROM イメージの取得は Docker daemon が行うため、Docker Desktop の Proxies 画面または daemon の設定で処理します。Dockerfile の RUN コマンドはビルド用コンテナ内で実行されるので、build.args から一時プロキシを渡せます。ただし、個人用のポートや認証情報を ENV としてイメージレイヤーに残さないでください。
{
"build": {
"dockerfile": "Dockerfile",
"args": {
"HTTP_PROXY": "http://host.docker.internal:7890",
"HTTPS_PROXY": "http://host.docker.internal:7890",
"NO_PROXY": "localhost,127.0.0.1"
}
}
}curl の成功後も、Git、apt、拡張機能をそれぞれ一度テストする
コンテナのターミナルで HTTP_PROXY、HTTPS_PROXY、NO_PROXY が設定されていることを確認し、Git とパッケージマネージャーのコマンドを個別に実行します。通常 Git は環境変数を読み込みます。まだ以前のアドレスを参照する場合は、Git 固有の設定も確認してください。
リモート拡張機能は、コンテナ側の VS Code Server がダウンロードします。remoteEnv を変更した後は Rebuild Container を実行し、出力パネルで marketplace へのリクエストを確認してください。
REPO_URL='https://github.com/octocat/Hello-World.git'
env | grep -i '_proxy'
git config --show-origin --get-regexp 'http.*proxy' || true
git ls-remote "$REPO_URL"
# 只有 Git 不读取环境变量时才临时写入
git config --global http.proxy http://host.docker.internal:7890
git config --global --unset-all http.proxycurl は成功するが、Git がまだ以前のポートへ接続する
git config --show-origin --get-regexp 'http.*proxy' を実行し、ユーザー設定またはリポジトリに残った設定を削除します。
apt update が失敗する
実際のリポジトリドメイン、証明書、/etc/apt/apt.conf.d にある個別のプロキシ設定を確認します。
プロジェクトは実行できるが、リモート拡張機能をインストールできない
Dev Containers のログで marketplace へのリクエストを探し、リモートサービスが remoteEnv を継承していることを確認します。
コンテナはインターネットへ接続できるが、ローカルデータベースへの接続に失敗する
データベースのサービス名とプライベートネットワークの範囲を NO_PROXY に追加します。
Rebuild の段階でまだ失敗する
daemon によるイメージ取得または Dockerfile の build args へ戻り、実行中のコンテナにはこれ以上変更を加えません。
共有リポジトリに個人用プロキシを固定値で書き込まない
チームプロジェクトでは、devcontainer.json で ${localEnv:HTTP_PROXY} を使って開発者のローカル環境を読み込むか、実際のアドレスを含まない .env.example を用意できます。
README には、HTTP_PROXY を http://host.docker.internal:7890 のような完全なアドレスで記述することを明記します。コミット前に、プロキシの URL にユーザー名、パスワード、token が含まれていないことを確認してください。
検証後は、docker pull、Rebuild Container、コンテナ内の Git とパッケージマネージャー、ローカルサービスへのアクセスをそれぞれ完了できる必要があります。失敗した項目があれば、その段階のログを残し、四層のネットワークを再び「Dev Container がネットワークへ接続できない」という一つの問題にまとめないでください。
