终端能下载,但 VPN 下 VS Code 扩展安装失败
容器里 curl 能用,扩展却始终装不上。在照搬代理设置之前,先比较本地编辑器与远程环境。
在容器终端里成功的下载,只能真实反映该终端的环境。它说明不了编辑器进程、扩展安装器,也说明不了扩展随后拉取的二进制文件。在这三者之间复制代理变量,会把一次失败的请求变成一下午的无关改动。
两种环境通常只在一个点上不同。找到这个点,比读两遍代理文档更快。
失败请求由哪个进程发出
一次安装过程中可能有三类请求失败,而它们各有自己的网络身份。编辑器先向 Marketplace 索取元数据和包 URL,然后下载安装包。之后扩展宿主才会运行代码,去拉取语言服务器或自带的二进制。坏在哪一步,决定了哪个进程需要代理,而错误界面很少点明这一步。
终端能用,只证明容器能上网,不证明编辑器能上网。去扩展日志里找它最后尝试的 URL。那里出现的主机名,能确定是哪个进程、适用哪条策略。
本地编辑器与远程容器是两个环境
在远程工作区里,扩展运行在它类型声明的那一侧。界面扩展留在本地编辑器,工作区扩展在容器里运行。在一边设的代理,另一边看不到;而重建会用配置文件重建容器环境,而不是用你在 shell 里导出的变量。这条分界解释了为什么同一个扩展在笔记本上装得上,在同一个项目里走 SSH 却失败。
动手之前先读安装位置。当日志报告的是远程安装时,起作用的是容器环境。
把代理放在请求发起的地方
对确实需要 HTTP 代理的 Dev Container,变量应写进容器配置,这样重建才能复现。下面的片段就是为该环境设置。占位地址代表你自己的网关,排除项不是可有可无的填充。
"containerEnv": {
"HTTP_PROXY": "http://proxy.corp.example:8080",
"HTTPS_PROXY": "http://proxy.corp.example:8080",
"NO_PROXY": "localhost,127.0.0.1,.internal.example"
}
变量名描述的是目标协议,所以 HTTPS_PROXY 的值完全可以以 http 开头。通过受支持的重建路径应用改动,并保留排除项,因为拦截内部主机的代理会弄坏容器依赖的服务。
把信任失败与可达性分开
能连上、随后返回证书校验错误的代理,比直接拒绝连接的代理走到了更靠后的一步。前一种失败需要把组织批准的信任材料装进发起请求的环境。后一种需要可达的地址和端口。把两者当成一个问题,得到的修法对两者都不管用。
关闭校验,或者用提权方式运行编辑器,都不是缺代理、缺信任链的修法。两者都是把显眼的错误换成无声的错误。之后再试同一个扩展,记下下一个失败的 URL。
env | grep -iE '^(http|https|no)_proxy='
code --install-extension ms-python.python --force
记下这个 URL 是工作区哪一侧产生的。一行写明步骤、主机和侧别的小注,比一份别人改过的设置清单更有价值,因为下一个人能复现的正是这条注释。