Docker配置网络代理实现外网镜像下载

系统环境

系统:Rocky Linux 9.3

Docker:27.4.1

服务器已配置代理,并且可访问外网,具体操作见:Rocky9安装Shadowsocks实现科学上网

背景

  • 部分镜像在国外,国内无法下载
  • 容器在运行时需要从国外网站下载依赖
  • 构建自定义镜像时需要访问国外网络

配置 Dockerd 代理

新建 docker 代理配置文件

在执行 docker pull 时,是由守护进程 dockerd 来执行。因此,代理需要配在 dockerd 的环境中。而这个环境,则是受 systemd 所管控,因此实际是 systemd 的配置。

sudo mkdir -p /etc/systemd/system/docker.service.d
sudo touch /etc/systemd/system/docker.service.d/proxy.conf

在这个 proxy.conf 文件(可以是任意 *.conf 的形式)中,添加以下内容:

[Service]
Environment="HTTP_PROXY=http://127.0.0.1:8118/"
Environment="HTTPS_PROXY=http://127.0.0.1:8118/"
Environment="NO_PROXY=localhost,127.0.0.1"
  • 配置解析

    由于Docker所在服务器已配置代理,可以科学上网,所以代理服务器IP为:127.0.0.1,指代本机。

    服务器配置代理使用的是 Privoxy,默认代理端口:8118

配置生效

重启docker以及守护进程

sudo systemctl daemon-reload
sudo systemctl restart docker

测试镜像拉取

下载一个国内无法拉取的谷歌镜像,如果成功则表明代理生效。

# 拉取谷歌镜像
root@shadowsockts:~# docker pull k8s.gcr.io/kube-proxy:v1.17.17

# 查看镜像
root@shadowsockts:~# docker images
REPOSITORY              TAG        IMAGE ID       CREATED         SIZE
calico/typha            v3.26.3    5993c7d25ac5   15 months ago   67.4MB
k8s.gcr.io/kube-proxy   v1.17.17   3ef67d180564   3 years ago     117MB

Container 代理

在容器运行阶段,如果需要代理上网,则需要配置 ~/.docker/config.json 。以下配置,只在Docker 17.07及以上版本生效。

修改防火墙配置

方式一:临时关闭防火墙

禁用 firewalld 和临时关闭 iptables,否则容器无法进行网络代理,防火墙会拦截代理请求

systemctl stop firewalld & systemctl disable firewalld
systemctl stop iptables

方式二:添加 iptables 规则,允许代理端口通过

iptables -I INPUT -p tcp --dport 8118 -j ACCEPT
iptables -I FORWARD -p tcp --dport 8118 -j ACCEPT
iptables -I OUTPUT -p tcp --dport 8118 -j ACCEPT

# # 如果使用 iptables-services:
service iptables save

# 如果使用 firewalld:
firewall-cmd --runtime-to-permanent
firewall-cmd --reload

我这里防火墙使用的是 iptables, 如果使用 firewalld 规则配置则不同。

修改 Privoxy 配置文件

vim /etc/privoxy/config

# 添加监听IP,192.168.6.221 为Privoxy所在服务器真实IP
listen-address  192.168.6.221:8118

Privoxy 配置文件

重启 Privoxy

systemctl restart privoxy

创建 Docker 配置文件

在 Docker 客户端上,在启动容器的用户的主目录中创建或编辑 ~/.docker/config.json 文件

mkdir ~/.docker
vim ~/.docker/config.json

# 编辑内容如下:
{
    "proxies":{
        "default":{
            "httpProxy":"http://192.168.6.221:8118",
            "httpsProxy":"https://192.168.6.221:8118",
            "noProxy":"localhost"
        }
    }
}

# 重启docker
sudo systemctl daemon-reload
sudo systemctl restart docker

将上面 prioxy 服务所在IP 替换成代理服务器真实IP和端口

  • 配置解析

    192.168.6.221 为网络代理服务器IP
    8118 是服务器代理端口。
    这个是用户级的配置,除了 proxies,docker login 等相关信息也会在其中。而且还可以配置信息展示的格式、插件参数等。
    
    此外,容器的网络代理,也可以直接在其运行时通过 -e 注入 http_proxy 等环境变量。这两种方法分别适合不同场景。
    config.json 非常方便,默认在所有配置修改后启动的容器生效,适合个人开发环境。在CI/CD的自动构建环境、或者实际上线运行的环境中,这种方法就不太合适,用 -e 注入这种显式配置会更好,减轻对构建、部署环境的依赖。当然,在这些环境中,最好用良好的设计避免配置代理上网。

测试 Docker Container 代理

创建一个容器,进入容器测试是否可以访问外网

# 创建容器
docker run -itd --name centos --restart always centos:7

# 进入容器
docker exec -it centos /bin/bash

# 查看容器内代理配置
[root@9d38f88f2411 /]# echo $http_proxy
http://192.168.204.151:8118
[root@9d38f88f2411 /]# echo $https_proxy
http://192.168.204.151:8118

# 在容器内访问谷歌
curl https://www.google.com

# 容器内查看ip
[root@shadowsockts /]# curl cip.cc
IP	: 112.169.175.22
地址	: 韩国  韩国

数据二	: 韩国 | KT电信

数据三	: 韩国 | 韩国电信

URL	: http://www.cip.cc/112.169.175.22

配置Container代理方式二

启动容器时,作为环境变量添加进去, 仅对当前启动容器有效。 这种方式比较常用

docker run -itd \
    --name centos \
    --restart always \
    --env "httpProxy:http://192.168.204.151:8118" \
    --env "httpsProxy:https://192.168.204.151:8118" \
    --env "noProxy:localhost" \
    centos:7

参考

https://kebingzao.com/2019/02/22/docker-container-proxy/

https://neucrack.com/p/286

https://hksanduo.github.io/2020/03/07/2020-03-07-docker-container-use-socks5-proxy/

Docker Build 代理

docker build . \
    --build-arg "HTTP_PROXY=http://192.168.204.151:8118" \
    --build-arg "HTTPS_PROXY=https://192.168.204.151:8118" \
    --build-arg "NO_PROXY=localhost,127.0.0.1,.example.com" \
    -t your/image:tag

参考

https://cloud.tencent.com/developer/article/1806455


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 george_95@126.com