本文目录
宿主机浏览器能上网,开发容器却可能卡在拉镜像、装依赖或下载扩展。把代理写进容器设置后仍失败,常是修改的位置没有对应实际发请求的程序。找准失败命令在哪里运行,再检查它能否连接宿主机代理,同时让数据库等内部服务继续直连。
Dev Containers 卡在哪一步:拉镜像、构建还是容器内下载?
记录失败命令和执行位置(Dev Containers 输出或容器终端),区分拉基础镜像、执行 Dockerfile、容器内 Git 或远程扩展下载。VS Code 的这个功能把开发环境放进容器;请求由不同进程发起,应按下表给实际失败的位置设置代理。
不同下载动作的代理设置
| 失败动作 | 实际发请求的组件 | 配置入口 |
|---|---|---|
| docker pull / 拉基础镜像 | Docker daemon | Docker Desktop 或 daemon 代理 |
| Dockerfile RUN apt/npm | 镜像构建阶段 | build args 或 BuildKit 配置 |
| 容器内 curl/Git/pip | 正在运行的容器 | containerEnv、remoteEnv 或工具配置 |
| VS Code 远程扩展下载 | 本机 VS Code 与容器侧服务 | 本机与容器网络设置、扩展自身配置 |
错误出现在“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 指向容器自己。Docker Desktop 在 Windows 与 macOS 提供 host.docker.internal;Linux Docker 可以通过 host-gateway 映射同名地址。
Clash 若只监听宿主机回环地址,容器仍可能连不到。开启允许局域网或把 mixed-port 监听到容器可达接口时,同时用系统防火墙限制来源;不应把 7890 直接暴露给公网。
下面前半段在已经运行的容器终端执行。最后的 docker run 只用于 Linux 宿主机终端,会新建临时测试容器;不在开发容器里重复执行。两处 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"]。不要同时在两个地方重复添加。
容器能访问宿主机端口后,设置 containerEnv 与 remoteEnv
容器里的 curl 通过代理收到 HTTP 响应后,再设置工具环境。下例用于 Dockerfile 或 image 项目,同时提供大小写变量以兼容不同工具;端口按实际 mixed-port 修改。Compose 项目把容器变量写到服务的 environment,仅将 remoteEnv 留在 devcontainer.json。
{
"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",
"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}",
"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 构建要单独配置
镜像拉取在 Docker Desktop 或构建器/daemon 侧配置;Dockerfile 的 RUN 则使用 build.args。Linux 上前面的 runArgs 映射只影响运行容器,构建阶段还需下面的 build.options 映射。不要把个人代理或凭据写成 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",
"http_proxy": "http://host.docker.internal:7890",
"https_proxy": "http://host.docker.internal:7890",
"no_proxy": "localhost,127.0.0.1"
},
"options": [
"--add-host=host.docker.internal:host-gateway"
]
}
}curl 成功后,Git、apt 和扩展仍要各测一次
在容器终端确认 HTTP_PROXY、HTTPS_PROXY 和 NO_PROXY 已经出现,然后分别执行 Git 和包管理器命令。Git 通常会读取环境变量;若它仍指向旧地址,再检查 Git 自己的配置。
通过扩展面板或 devcontainer.json 安装扩展时,本机与容器侧 VS Code Server 都需要能访问 Marketplace 和下载 CDN。修改 remoteEnv 后重连并打开新终端,从输出面板确认实际失败请求;无需只为 remoteEnv 重建整个容器。
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 -c http.proxy=http://host.docker.internal:7890 ls-remote "$REPO_URL"curl 成功,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/包管理器和本地服务访问。失败时保存对应命令和日志,按照本文的配置入口检查,不必同时修改所有代理设置。
