终端代理
docker 代理怎么设
要点
问:三处代理各管什么?
短答:拉镜像归 daemon,容器里的程序归容器,构建时 RUN 的命令归构建容器。
| 场景 | 谁在联网 | 在哪设 | 何时生效 |
|---|---|---|---|
| docker pull、拉基础镜像 | dockerd | Linux:systemd 配置或 daemon.json;Docker Desktop:设置页 | 重启 daemon 后 |
| 容器里的 apt、pip、curl | 容器内的进程 | ~/.docker/config.json 的 proxies,或启动容器时加 --env 参数 |
新建的容器 |
| docker build 时 RUN 的命令 | 构建容器 | config.json 的 proxies 会自动变成构建参数,或用 –build-arg | 下一次构建 |
dockerd[进程]Docker 的后台服务,镜像是它去仓库拉的。① 它不读你终端里的环境变量;② Linux 上它跑在宿主机,127.0.0.1 就是宿主机本身。参见:容器代理。
容器代理[配置项]写进容器环境变量的 HTTP_PROXY 一类设置。① 只对新建的容器生效;② 地址要写容器能连到的宿主机地址。
问:Linux 上怎么给 daemon 设代理?
短答:在 docker.service 旁边加一个 systemd 配置片段,写上三行环境变量,重载后重启。
sudo mkdir -p /etc/systemd/system/docker.service.d
sudo tee /etc/systemd/system/docker.service.d/http-proxy.conf <<'EOF'
[Service]
Environment="HTTP_PROXY=http://127.0.0.1:7890"
Environment="HTTPS_PROXY=http://127.0.0.1:7890"
Environment="NO_PROXY=localhost,127.0.0.1"
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
sudo systemctl show --property=Environment docker
也可以写进 /etc/docker/daemon.json,官方文档把这种写法放在前面,并说明 daemon.json 里的设置优先于环境变量:
{
"proxies": {
"http-proxy": "http://127.0.0.1:7890",
"https-proxy": "http://127.0.0.1:7890",
"no-proxy": "localhost,127.0.0.1"
}
}
改完同样执行 sudo systemctl restart docker。rootless 模式的配置片段放在 ~/.config/systemd/user/docker.service.d/ 下,命令改用 systemctl –user,不加 sudo。7890 请改为你客户端里显示的端口;systemd 配置里的地址若含百分号这类特殊字符,要写成两个 %% 转义。
问:Docker Desktop 在哪设?
短答:在设置页的 Resources → Proxies 里设,daemon.json 里的 proxies 对它无效。
- 打开 Docker Desktop 的 Settings → Resources → Proxies。
- 代理客户端已经开了系统代理的,选 System proxy 沿用;否则选 Manual configuration,在 Web Server (HTTP) 和 Secure Web Server (HTTPS) 两栏填客户端的地址和端口,下方可写不走代理的地址。
- 新版本把这里分成 Docker Desktop proxy 和 Containers proxy 两块,docker pull 走的是后一块;后一块没配时,拉镜像才退回用前一块。
- 按 Apply 保存,Docker Desktop 会自己重启引擎。
问:容器里的程序怎么走代理?
短答:在 ~/.docker/config.json 里写 proxies,之后新建的容器和构建都会自动带上这几个变量。
{
"proxies": {
"default": {
"httpProxy": "http://172.17.0.1:7890",
"httpsProxy": "http://172.17.0.1:7890",
"noProxy": "localhost,127.0.0.1"
}
}
}
这里的地址不能写 127.0.0.1。Linux 上默认网桥 docker0 的宿主机地址通常是 172.17.0.1(用 ip addr show docker0 确认);Docker Desktop 上写 host.docker.internal。代理客户端还要打开允许局域网连接,否则只听本机回环,容器连不进来。保存后不用重启,对之后新建的容器生效。Docker 文档提醒,这些变量以明文存在容器配置里,代理地址带账号密码时要留意。
问:怎么确认已经走代理?
短答:daemon 看 docker info,容器里用 curl 取一次出口 IP。
docker info | grep -i proxy
docker pull hello-world
docker run \
--rm curlimages/curl -s https://chageejichang.co/api/chukou
docker info 里出现 HTTP Proxy、HTTPS Proxy 两行,说明 daemon 读到了设置;hello-world 能拉下来,说明拉镜像那条路通了。末一条在容器里访问本站的出口接口,返回的 IP 和 ASN 就是容器经代理后的出口;本站接口打不开时,把地址改为第三方的 https://ipinfo.io/json。容器里返回的出口和宿主机上用 curl 取到的不一致,说明容器没走代理,或者走了另一条分流规则。
问:Linux 和 Docker Desktop(Windows、macOS)有什么不同?
短答:设 daemon 代理的位置、容器连宿主机的地址、重启的方式都不同。
| 项 | Linux(Docker Engine) | Docker Desktop(Windows、macOS) |
|---|---|---|
| daemon 代理 | systemd 配置片段或 daemon.json | 设置页 Resources → Proxies |
| 容器里连宿主机 | docker0 网桥地址,常见 172.17.0.1 | host.docker.internal |
| 重启 daemon | sudo systemctl restart docker | 设置页按 Apply 自动重启 |
| config.json 位置 | ~/.docker/config.json |
Windows 为 %USERPROFILE%\.docker\config.json,macOS 同 Linux |
问:不用了怎么撤销?
短答:删掉配置片段或 daemon.json 里的 proxies,重启 daemon;再从 config.json 里删掉 proxies。
sudo rm /etc/systemd/system/docker.service.d/http-proxy.conf
sudo systemctl daemon-reload
sudo systemctl restart docker
docker info | grep -i proxy
末一条不再有输出即已清除。Docker Desktop 在 Proxies 页改回 No proxy 或 System proxy 后按 Apply。git 拉 GitHub 被重置的情况见 Recv failure: Connection was reset,git 自己的代理设法见 git set proxy;容器里解析域名出错时,先按 DNS 检测 一页查解析器。