2024-09-13 开始,所有的 docker 服务都被墙了,而且国内的镜像相继停止服务。
在兔子搞开发,代理总是绕不开的,docker 挂代理的方式又比较复杂,网上找了很多资料,有的对有的不对,在这里根据场景整理一下希望帮到大家。
0 Docker 的三个环境开始前讲一下 Docker 的三个环境。
Docker 是一个虚拟化容器服务,要管理的环境很多,稍有不注意就容易混淆。
第一个环境是 docker daemon 守护程序,就是运行在我们电脑上的 docker 软件,它负责管理镜像和容器。我们在命令行输入的内容,就是由 docker daemon 来处理的。
第二个环境是 docker build 环境。也是一个容器环境。docker 在 build 镜像时总是要新建一个临时容器,这个容器带了一个环境,build 的过程就在该环境中运行。
第三个环境是容器 container 自己的环境。每个运行的容器拥有的环境不同。
有了以上理解,下文将根据三个环境,分为三种不同的场景,提出不同的解决方法。
1 场景一:docker pull 失败比较典型的情况就是访问链接失败:
Error response from daemon: Head "***“: Get "***": net/http: TLS handshake timeout
也有可能是其他报错,例如 EOF 0 之类错误。这时候就要考虑要给 docker daemon 挂代理了。有以下两种解决方案
1.1 推荐的方法:修改 daemon.json 配置文件首先,找到你的 daemon.json 配置文件,比较坑的是,不同的 docker 安装方式这个文件的位置不同。
然后,添加以下内容,把你自己本地的代理地址写进去:
{ "proxies" : { "http-proxy" : ":7890", "no-proxy" : "localhost,127.0.0.0/8", "https-proxy" : ":7890" } }
然后重启一下 docker 服务,使其生效。若要检查生效情况,可以执行:
$ docker info ... HTTP Proxy: :7890 HTTPS Proxy: :7890 No Proxy: localhost,127.0.0.1 ...
如果出现以上几行的话,说明代理配置成功,这时候可以尝试 docker pull 看看是否正常。
1.2 方式 2:适用于 Linux 部署,修改 systemd 自启动配置一般情况下,用上面的方法就可以了。不过官方文档里,另外还提出了一种方案,适合 linux 环境下直接在 systemd 中配置代理。简单介绍一下。
就是新增 systemd 配置文件/etc/systemd/sysytem/docker.service.d/http_proxy.conf,加入以下内容
[Service] Environment="HTTP_PROXY=http://127.0.0.1:7890" Environment="HTTPS_PROXY=https://127.0.0.1:7890" Environment="NO_PROXY=localhost,127.0.0.1"
更详细的介绍,请见Daemon proxy configuration | Docker Docs。
2 场景二:docker build 时网络连接失败docker build 是创建镜像的命令,创建镜像需要网络连接。这时候就要给 docker build 的临时容器指定代理。
2.1 推荐的方式:使用宿主机网络docker build 时,docker 会创建一个临时容器,在容器中组装镜像。
根据这篇文章:使用代理进行 docker build 问题的解决思路_docker build proxy-CSDN博客
如果宿主机没有设置环境变量,那么要先配置好本地代理。如果已经在 zsh 或者 bash 中配置了,那么无须重复配置:
export http_proxy=":7890" export HTTP_PROXY=":7890" export https_proxy=":7890" export HTTPS_PROXY=":7890"
然后使用宿主网络运行 docker build:
docker build --network host .
以上方法适用于 linux 和 macOS 环境。win 我暂时没有测试,不过思路是一样的。
2.2 方式 2:修改 docker cli 的代理配置根据:Proxy configuration | Docker Docs
找到位于 ~/.docker/config.json 的配置文件(如果没有就新建一个),该文件是用户级的,不同用户可以使用不同的配置文件。
{ "proxies": { "default": { "httpProxy": ":3128", "httpsProxy": "https://proxy.example.com:3129", "noProxy": "*.test.example.com,.example.org,127.0.0.0/8" } } }
这种方式不太推荐,因为以上配置文件中的地址,必须是虚拟网络中宿主机的地址,而不是简单的 127.0.0.1,关于如何找虚拟网络中找宿主机的地址,见 3.1。
2.3 方式 3:使用 docker build --build-arg 参数根据 配置 HTTP/HTTPS 网络代理 | Docker — 从入门到实践,这种情况下,可以在 docker build 时,使用 build-arg 参数指定 build 时的代理。
docker build \ --build-arg "HTTP_PROXY=http://proxy.example.com:8080/" \ --build-arg "HTTPS_PROXY=http://proxy.example.com:8080/" \ --build-arg "NO_PROXY=localhost,127.0.0.1,.example.com" .
也一样,还是有宿主机网络的问题。
3 场景三:docker run 的容器无法连接网络每一个运行的容器都有自己的环境,这时候就需要为不同的容器创建代理。
3.1 推荐的方式:指定 docker run --env 环境变量参数为容器指定代理,做以下几个步骤:
第一步,列出所有 docker 正在使用的网络环境。
$ docker network ls NETWORK ID NAME DRIVER SCOPE 4399b0394284 bridge bridge local e80b70352e66 host host local 6aa903fc462f none null local
第二步,找到对应的网络配置,这里以 bridge 为例(一般 docker run 默认是 bridge 网络),找到 Gateway 网关地址(网关一般就是宿主机的地址)。
$ docker network inspect bridge [ { ... "IPAM": { "Driver": "default", "Options": null, "Config": [ { "Subnet": "172.17.0.0/16", "Gateway": "172.17.0.1" } ] }, ... } ]
示例中的 ip 地址为 172.17.0.1,记下来。
注意:
第三步:运行容器并指定代理参数
docker run \ --env HTTP_PROXY=":7890/"\ --env HTTPS_PROXY=":7890/"\ --env http_proxy=":7890/"\ --env https_proxy=":7890/"\ --env NO_PROXY="localhost,127.0.0.1,.example.com"\ {your_image}
基本就可以了,可以进入容器终端看看,验证下配置是否生效。
3.2 方式 2:修改 docker cli 命令行工具的代理配置同 2.2。不过不推荐,因为不同容器也许挂载在不同的网络下,宿主机的地址可能不同,如果用固定 IP 访问宿主机,就会连接不上。
-1 结束语我以为这篇文章会很简单,没想到一不小心写了这么多,足以见得 docker 的代理配置实在是挺反人类的。
希望对你有用。