Docker的网络代理
下文涉及到代理的部分,将假设有一个本地HTTP的网络代理:http://127.0.0.1:1080
1. Docker pull
Docker在拉取镜像时,还是借助宿主机的网络,所以设置源和设置环境变量中的网络代理变量均是有效的
1.1. 更换Docker源
在2024年6月后,国内不少Docker源都失效了,如果能找到可用的国内源,更换源这个方法还是很好用的
更换源,编辑:/etc/docker/daemon.json
JSONcontent_copy{ "registry-mirrors": [ "https://registry.docker-cn.com", "https://docker.mirrors.ustc.edu.cn", "https://hub-mirror.c.163.com", "https://mirror.baidubce.com" ] }
重启docker应用新的源
Bashcontent_copysudo systemctl restart docker
如果拉取不成功,可以借助 journalctl
查看错误
journalctl -xue docker.service
1.2. 网络代理1.2.1. 临时环境变量
临时设置系统环境变量:
Bashcontent_copyexport HTTP_PROXY=http://127.0.0.1:1080 export HTTPS_PROXY=http://127.0.0.1:1080
然后拉取镜像
Bashcontent_copysudo -E docker pull hello-world
-E
用于让sudo用户继承当前普通用户的非安全环境变量(HTTP_PROXY和HTTPS_PROXY)
这个代理设置仅对当前会话生效,在退出后将不再生效
1.2.2. daemon.json
如果希望拉取时的代理设置永久生效,可以通过修改 daemon.json
来实现
编辑:/etc/docker/daemon.json
JSONcontent_copy{ "proxies": { "http-proxy": "http://127.0.0.1:1080", "https-proxy": "http://127.0.0.1:1080", "no-proxy": "*.test.example.com,.example.org" }, "ipv6": false }
走网络代理的时要注意禁用系统 ipv6
,否则容易出现在 ipv4
环境下访问 ipv6
导致的网络错误
重启docker应用网络代理设置:
Bashcontent_copysudo systemctl restart docker
1.2.3. 永久环境变量
除了修改 daemon.json
实现网络代理永久生效外,也可以通过修改docker运行时的环境变量来实现
编辑:/etc/systemd/system/multi-user.target.wants/docker.service
INIcontent_copy... [Service] Environment="HTTP_PROXY=http://127.0.0.1:1080" Environment="HTTPS_PROXY=http://127.0.0.1:1080" ...
在service节点中添加环境变量,这样每一次拉取都会走网络代理
docker.service的文件位置在不同系统中不同,可以通过
find
来进行查找该文件
重启docker以使环境变量生效
Bashcontent_copysudo systemctl daemon-reload sudo systemctl restart docker
2. Docker Build
无论是修改 daemon.json
还是修改 docker.service
,其本质是影响了Docker的Daemon进程环境变量
而与拉取不同,在构建时,每个Dockerfile的RUN指令都在一个全新的容器中执行,这些容器不会继承Docker Daemon进程的环境变量
如果在构建步骤中,有一些指令如 curl/wget
需要使用代理,则需要修改编辑Dockerfile文件,添加 http_proxy
和 https_proxy
变量:
... ARG http_proxy ARG https_proxy ENV http_proxy=${http_proxy} ENV https_proxy=${https_proxy} ...
这里采用在构建时传入 http_proxy
和 https_proxy
变量会更加灵活
如刚才所说,构建阶段是完全网络隔离的,所以 127.0.0.1
是无法指向宿主机的,需要填入真实的宿主机IP
先使用 ip -a
获取到宿主机的真实IP,如:
$ ip -a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever 2: enp4s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000 link/ether c8:7f:54:a9:98:d1 brd ff:ff:ff:ff:ff:ff inet 192.168.1.2/24 brd 192.168.15.255 scope global enp4s0 valid_lft forever preferred_lft forever ... 106 docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default link/ether 02:42:34:65:16:f5 brd ff:ff:ff:ff:ff:ff inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0 valid_lft forever preferred_lft forever
192.168.1.2
和 172.17.0.1
两个地址都可以被容器访问到,那么构建参考如下:
sudo docker build \ --build-arg http_proxy=http://192.168.1.2:1080 \ --build-arg https_proxy=http://192.168.1.2:1080 \ -t your-image .
3. Docker Container
Docker在运行时,容器要使用网络代理,则需要设置容器的全局网络代理变量,类似于在Linux Shell中设置http_proxy
和 http_proxy
容器在运行时,通过-e
参数设置环境变量:
sudo docker run \ -e http_proxy=http://192.168.1.2:1080 \ -e https_proxy=http://192.168.1.2:1080 \ your-image
与前文一致,容器内的环境是独立的,所以要将代理指向宿主机而不是 127.0.0.1
文章来源:
Author:chancel
link:http://www.chancel.me/markdown/docker-network-proxy