使用来自主机的 socks5 代理进行 docker 构建
Use socks5 proxy from host for docker build
要构建某个图像,我需要创建一个隧道并docker将此隧道用作 socks5 代理(也将代理用于 DNS)。
所以现在我遇到了几个问题:
- 如何docker使用主机上的代理?
- 如何让docker使用代理获取基础镜像?
- 如何让docker使用代理执行运行指令?
- 如何使 docker 使用 ADD 指令的代理?
因为我花了一整天的时间研究这个,这里是答案。
我将在下面留下部分 incomplete/wrong/old 的答案,因为我今天设置了一个新系统并且需要重新弄清楚所有问题,因为旧答案的某些部分不再有意义了。
使用 localhost:port
无效。在解决 this 问题之前,您需要使用 docker0 网络接口的 IP 地址(在我的例子中是 172.17.0.1
)。如果您的主机 OS 是 linux,您可以通过将额外的 --network=host
参数传递给 docker build
来使用 localhost:port
,如其他答案中所述。
和 3. 将此内容(如果需要,更改 IP 和端口)放入 ~/.docker/config.json
(注意协议是 socks5h)
{
"proxies":
{
"default":
{
"httpProxy": "socks5h://172.17.0.1:3128",
// or "httpProxy": "socks5h://localhost:3128", with --network=host
"httpsProxy": "socks5h://172.17.0.1:3128",
"noProxy": ""
}
}
}
- 似乎
ADD
命令是使用主机的(代理)环境变量执行的,忽略了config.json
中的那些。使事情变得更复杂的是,由于守护程序通常是 运行 root
用户,因此仅选择 root
用户的环境变量。甚至更复杂,因为主机当然需要使用 localhost 作为代理的主机。最重要的是:在这种情况下,无论出于何种原因,协议都需要 socks5
(最后缺少 h
)。
在我的例子中,由于我切换到 WSL2 并在 WSL2 中使用 docker(手动启动 dockerd
docker 守护进程),我只是在调用之前导出所需的环境变量到 dockerd
:
#!/bin/bash
# Start Docker daemon automatically when logging in if not running.
RUNNING=`ps aux | grep dockerd | grep -v grep`
if [ -z "$RUNNING" ]; then
unset http_proxy https_proxy HTTP_PROXY HTTPS_PROXY no_proxy NO_PROXY
export http_proxy=socks5h://localhost:30000
sudo -E dockerd > /dev/null 2>&1 &
disown
fi
如果您在 linux 机器上进行了“常规”设置,您可以使用对 4. 的旧答案,但请注意您可能还需要使用 localhost。
Incomplete/wrong/old 回答从这里开始
- 使用localhost:port 无效。在 this 问题解决之前,您需要使用 docker0 网络接口的 IP 地址(在我的例子中是 172.17.0.1)。
- 这个答案也适用于问题 3。只需将此内容(如果需要,更改 IP 和端口)放入
~/.docker/config.json
(注意协议是 socks5h)
{
"proxies":
{
"default":
{
"httpProxy": "socks5h://172.17.0.1:3128",
"httpsProxy": "socks5h://172.17.0.1:3128",
"noProxy": ""
}
}
}
- 我不知道为什么(编辑:现在我知道了,这是因为
dockerd
是 运行 作为 root 并且它不会从普通用户那里获取代理环境变量),但是对于添加指令以前的设置不适用(名称不通过代理解析)。我们需要把这个内容放到/etc/systemd/system/docker.service.d/http-proxy.conf
[Service]
Environment="HTTP_PROXY=socks5://172.17.0.1:3128/"
然后
sudo systemctl daemon-reload
sudo systemctl restart docker
(这只是 wrong/unneeded 和答案 2。)此外,对于像 yum
这样的包管理器,为了能够在构建期间更新包,您需要像这样传递环境变量:
docker build --build-arg http_proxy=socks5://172.17.0.1:3128
通过在“docker build ...”命令中添加“--network=host”选项来使用 localhost:port。
sudo iptables -t nat -N REDSOCKS
sudo iptables -t nat -A REDSOCKS -d 0.0.0.0/8 -j RETURN
sudo iptables -t nat -A REDSOCKS -d 10.0.0.0/8 -j RETURN
sudo iptables -t nat -A REDSOCKS -d 127.0.0.0/8 -j RETURN
sudo iptables -t nat -A REDSOCKS -d 169.254.0.0/16 -j RETURN
sudo iptables -t nat -A REDSOCKS -d 172.16.0.0/12 -j RETURN
sudo iptables -t nat -A REDSOCKS -d 224.0.0.0/4 -j RETURN
sudo iptables -t nat -A REDSOCKS -d 240.0.0.0/4 -j RETURN
sudo iptables -t nat -A REDSOCKS -d 192.168.0.0/16 -j RETURN
sudo iptables -t nat -A REDSOCKS -p tcp -j REDIRECT --to-ports 5000
sudo iptables -t nat -A REDSOCKS -d 172.17.0.0/12 -j RETURN
sudo iptables -t nat -A OUTPUT -p tcp -o docker0 -j REDSOCKS
sudo iptables -t nat -A PREROUTING -p tcp -i docker0 -j REDSOCKS
为了在本地将容器连接到 socks5,也就是说,整个 Internet 都转到代理,容器必须能够访问 machine 主机。
要在 Linux 中访问 machine 主机,您必须:
将 --network="host" 放入 运行 命令中:
docker 运行 --name test --network="host" --env http_proxy="socks5://127.0.0.1:1080 " --env https_proxy="127.0.0.1:1080" nginx sh -c "curl ifconfig.io"
对于 mac 和 windows 用户我们使用 host.local.internal:local_port:
docker 运行 --name test --env http_proxy="socks5://host.local.internal:1080" --env https_proxy="socks5://host.local.internal:1080" nginx sh -c "curl ifconfig.io"
要构建某个图像,我需要创建一个隧道并docker将此隧道用作 socks5 代理(也将代理用于 DNS)。
所以现在我遇到了几个问题:
- 如何docker使用主机上的代理?
- 如何让docker使用代理获取基础镜像?
- 如何让docker使用代理执行运行指令?
- 如何使 docker 使用 ADD 指令的代理?
因为我花了一整天的时间研究这个,这里是答案。
我将在下面留下部分 incomplete/wrong/old 的答案,因为我今天设置了一个新系统并且需要重新弄清楚所有问题,因为旧答案的某些部分不再有意义了。
使用
localhost:port
无效。在解决 this 问题之前,您需要使用 docker0 网络接口的 IP 地址(在我的例子中是172.17.0.1
)。如果您的主机 OS 是 linux,您可以通过将额外的--network=host
参数传递给docker build
来使用localhost:port
,如其他答案中所述。和 3. 将此内容(如果需要,更改 IP 和端口)放入
~/.docker/config.json
(注意协议是 socks5h)
{
"proxies":
{
"default":
{
"httpProxy": "socks5h://172.17.0.1:3128",
// or "httpProxy": "socks5h://localhost:3128", with --network=host
"httpsProxy": "socks5h://172.17.0.1:3128",
"noProxy": ""
}
}
}
- 似乎
ADD
命令是使用主机的(代理)环境变量执行的,忽略了config.json
中的那些。使事情变得更复杂的是,由于守护程序通常是 运行root
用户,因此仅选择root
用户的环境变量。甚至更复杂,因为主机当然需要使用 localhost 作为代理的主机。最重要的是:在这种情况下,无论出于何种原因,协议都需要socks5
(最后缺少h
)。
在我的例子中,由于我切换到 WSL2 并在 WSL2 中使用 docker(手动启动 dockerd
docker 守护进程),我只是在调用之前导出所需的环境变量到 dockerd
:
#!/bin/bash
# Start Docker daemon automatically when logging in if not running.
RUNNING=`ps aux | grep dockerd | grep -v grep`
if [ -z "$RUNNING" ]; then
unset http_proxy https_proxy HTTP_PROXY HTTPS_PROXY no_proxy NO_PROXY
export http_proxy=socks5h://localhost:30000
sudo -E dockerd > /dev/null 2>&1 &
disown
fi
如果您在 linux 机器上进行了“常规”设置,您可以使用对 4. 的旧答案,但请注意您可能还需要使用 localhost。
Incomplete/wrong/old 回答从这里开始
- 使用localhost:port 无效。在 this 问题解决之前,您需要使用 docker0 网络接口的 IP 地址(在我的例子中是 172.17.0.1)。
- 这个答案也适用于问题 3。只需将此内容(如果需要,更改 IP 和端口)放入
~/.docker/config.json
(注意协议是 socks5h)
{
"proxies":
{
"default":
{
"httpProxy": "socks5h://172.17.0.1:3128",
"httpsProxy": "socks5h://172.17.0.1:3128",
"noProxy": ""
}
}
}
- 我不知道为什么(编辑:现在我知道了,这是因为
dockerd
是 运行 作为 root 并且它不会从普通用户那里获取代理环境变量),但是对于添加指令以前的设置不适用(名称不通过代理解析)。我们需要把这个内容放到/etc/systemd/system/docker.service.d/http-proxy.conf
[Service]
Environment="HTTP_PROXY=socks5://172.17.0.1:3128/"
然后
sudo systemctl daemon-reload
sudo systemctl restart docker
(这只是 wrong/unneeded 和答案 2。)此外,对于像 yum
这样的包管理器,为了能够在构建期间更新包,您需要像这样传递环境变量:
docker build --build-arg http_proxy=socks5://172.17.0.1:3128
通过在“docker build ...”命令中添加“--network=host”选项来使用 localhost:port。
sudo iptables -t nat -N REDSOCKS
sudo iptables -t nat -A REDSOCKS -d 0.0.0.0/8 -j RETURN
sudo iptables -t nat -A REDSOCKS -d 10.0.0.0/8 -j RETURN
sudo iptables -t nat -A REDSOCKS -d 127.0.0.0/8 -j RETURN
sudo iptables -t nat -A REDSOCKS -d 169.254.0.0/16 -j RETURN
sudo iptables -t nat -A REDSOCKS -d 172.16.0.0/12 -j RETURN
sudo iptables -t nat -A REDSOCKS -d 224.0.0.0/4 -j RETURN
sudo iptables -t nat -A REDSOCKS -d 240.0.0.0/4 -j RETURN
sudo iptables -t nat -A REDSOCKS -d 192.168.0.0/16 -j RETURN
sudo iptables -t nat -A REDSOCKS -p tcp -j REDIRECT --to-ports 5000
sudo iptables -t nat -A REDSOCKS -d 172.17.0.0/12 -j RETURN
sudo iptables -t nat -A OUTPUT -p tcp -o docker0 -j REDSOCKS
sudo iptables -t nat -A PREROUTING -p tcp -i docker0 -j REDSOCKS
为了在本地将容器连接到 socks5,也就是说,整个 Internet 都转到代理,容器必须能够访问 machine 主机。
要在 Linux 中访问 machine 主机,您必须: 将 --network="host" 放入 运行 命令中:
docker 运行 --name test --network="host" --env http_proxy="socks5://127.0.0.1:1080 " --env https_proxy="127.0.0.1:1080" nginx sh -c "curl ifconfig.io"
对于 mac 和 windows 用户我们使用 host.local.internal:local_port:
docker 运行 --name test --env http_proxy="socks5://host.local.internal:1080" --env https_proxy="socks5://host.local.internal:1080" nginx sh -c "curl ifconfig.io"