文章目录
由于众所周知的原因,使用 Docker 时可能会遇到诸多网络问题。然而,网络上关于此的文章充斥着杂乱无章的错误内容,而官方文档的描述也没有特别清楚。本文依据文档和亲身实践,整理 Docker 中各种代理配置方法,留供参考。
Docker daemon 代理
当执行 docker pull
拉取镜像,一般是从 DockerHub 等仓库拉取,此时容易遇到网络问题。
这一拉取过程实际上是 Docker daemon 在执行,而它是由 systemd 启动管理的,并不直接使用我们 shell 中配置的代理环境变量。为了让其走代理,需要编写其 systemd 配置。
文件位置:/etc/systemd/system/docker.service.d/http-proxy.conf
。
内容示例:
[Service]
Environment="HTTP_PROXY=http://127.0.0.1:1080"
Environment="HTTPS_PROXY=http://127.0.0.1:1080"
保存配置后,需要重启 Docker daemon。注意:这会重启所有容器。
sudo systemctl daemon-reload
sudo systemctl restart docker
相关文档:Configure the daemon to use a proxy。
容器内代理
容器内的应用或许需要访问网络,我们也希望其流量通过代理。这需要在容器内配置环境变量。
可以在 Dockerfile 或者 docker run
的时候设定环境变量,但这要求对每个容器都写重复的配置。有一种更方便的方式:进行如下配置后,启动的容器都会自动设置 http_proxy
等环境变量。
文件位置:~/.docker/config.json
内容示例:
{
"proxies": {
"default": {
"httpProxy": "http://example:1080",
"httpsProxy": "http://example:1080",
"noProxy": "*.test.example.com,.example.org,127.0.0.0/8,192.168.0.0/16"
}
}
}
指定 httpProxy
属性值,相当于在容器内同时设定 http_proxy
和 HTTP_PROXY
两个环境变量。
保存配置后,无需重启任何服务。在保存配置之后启动的 docker 容器,都会自动配置对应环境变量(之前的容器不会改变)。然而,应用是否读取该环境变量并使用代理设置,取决于应用的实现。这并不是一个标准。
⚠️ 注意:此处环境变量会在容器内被读取,所以地址 127.0.0.1 指的是容器自身,而非宿主机。
⚠️ 注意:如果容器是以 root 模式启动的(使用 sudo),上面所述的 ~/.docker/config.json
其实指的是 /root/.docker/config.json
。
⚠️ 注意:curl 等工具并不支持 socks 代理,只支持 http。所以建议统一配置 http 代理。
相关文档:Use a proxy server with the Docker CLI。
Build 时代理
在运行 docker build
时,许多操作容易遇到网络问题。这个 build 过程其实也在一个 Docker 容器中进行,所以读取不到我们 shell 环境的代理环境变量,也访问不到我们的主机网络。
解决方案是,首先指定 build 时使用的网络环境为 host:
docker build --network=host
或者在 docker-compose.yml
中:
build:
context: .
network: host
dockerfile: Dockerfile
接下来,在 Dockerfile 中,设置环境变量:
ENV http_proxy "http://127.0.0.1:1080"
ENV HTTP_PROXY "http://127.0.0.1:1080"
ENV https_proxy "http://127.0.0.1:1080"
ENV HTTPS_PROXY "http://127.0.0.1:1080"
我的终极代理解决方案
我们希望容器内外的网络都使用同样的代理。为了方便容器内的访问,更好的选择是将代理程序作为一个容器运行。
我的解决方案是:单独启动一个名为 proxy 的容器,专门负责进行网络代理;映射 1080 端口,为宿主机提供代理。
- 容器外:只要配置代理地址
http://127.0.0.1:1080
。 - 容器内:只要加入 proxy 同一网络,并配置代理地址
http://proxy:1080
。
⚠️ 注意:不要将此端口暴露在公网中,否则被 ISP 扫描到可能要写保证书。
Happy Self-hosting!