使用主机的socks5代理来构建docker

16
为了构建一个特定的映像,我需要创建一个隧道,并使docker使用这个隧道作为socks5代理(也可用于DNS)。
现在我面临以下几个问题:
1. 如何让docker使用主机上的代理? 2. 如何让docker使用代理获取基础映像? 3. 如何让docker在RUN指令中使用代理? 4. 如何让docker在ADD指令中使用代理?
5个回答

31

由于我一整天都在研究这个问题,以下是答案。

我将保留部分不完整/错误/旧的答案,因为我今天设置了一个新系统,需要重新解决所有问题,因为旧答案的某些部分不再合理。

  1. 使用 localhost:port 是无效的,直到此问题得到解决,您需要使用 docker0 网络接口的 IP 地址(在我的情况下是 172.17.0.1)。如果您的主机操作系统是 linux,则可以通过向 docker build 传递额外的 --network=host 参数来使用 localhost:port,如其他答案中所述。

  2. 只需将此内容(必要时更改 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": ""
            }
        }
    }
  1. 看起来 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。

以下是不完整/错误/过时的答案

  1. 使用localhost:port无法正常工作。在问题解决之前,您需要使用docker0网络接口的IP地址(在我的情况下为172.17.0.1)。
  2. 此答案也适用于问题3。只需将此内容(如有需要,请更改IP和端口)放入~/.docker/config.json中(请注意协议为socks5h)。
    {
        "proxies":
        {
            "default":
            {
                "httpProxy": "socks5h://172.17.0.1:3128",
                "httpsProxy": "socks5h://172.17.0.1:3128",
                "noProxy": ""
            }
        }
    }
  1. 我不知道为什么(编辑:现在我知道了,是因为dockerd作为root用户运行,并且它没有从普通用户中获取代理环境变量),但对于ADD指令,以前的设置不适用(名称不能通过代理解析)。我们需要将此内容放入/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

(这在答案2中是错误的/不必要的。)另外,对于像yum这样的软件包管理器,在构建过程中能够更新软件包,您需要像这样传递环境变量:

docker build --build-arg http_proxy=socks5://172.17.0.1:3128

你尝试过添加虚拟网络设备来解决 Docker 容器无法“看到”主机的问题吗?这意味着使用固定的 169.254.X.X 类型地址,而且无论 /etc/docker/daemon.json 中的 Docker 配置如何(默认地址池设置可能会更改 172.17 地址),它始终是相同的。 - Keeely
1
对于那些可能会困惑于 config.json 的位置以及应该将其放在哪里的人,只需在 Dockerfile 旁边创建它,并在该 Dockerfile 中使用此名称设置 DOCKER_CONFIG 环境变量,例如:ENV DOCKER_CONFIG=config.json。 - Iman Hajimostafazadeh
1
@ImanHajimostafazadeh 我认为在您的用户主目录中的.docker/或者更好的.config/docker/文件夹中创建此文件仍然更容易。 - JSamir

1

使用localhost:port的方法是在“docker build…”命令中添加“--network=host”选项。


仅支持Linux https://docs.docker.com/network/host/ - Manuel Alves

-1
为了将一个容器本地连接到socks5,即整个互联网走代理,该容器必须能够访问主机。
在Linux中访问主机,您需要在运行命令中添加--network="host":
docker run --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 run --name test --env http_proxy="socks5://host.local.internal:1080" --env https_proxy="socks5://host.local.internal:1080" nginx sh -c "curl ifconfig.io"

完全不工作。 - Vidy Videni

-1

保持简单

创建或编辑 /etc/systemd/system/docker.service.d/proxy.conf 文件,并添加:

[Service]
Environment="HTTP_PROXY=socks5://127.0.0.1:<PROXY_PORT>"
Environment="HTTPS_PROXY=socks5://127.0.0.1:<PROXY_PORT>"

将替换为您的代理端口。然后,重新加载systemd并重新启动Docker:
sudo systemctl daemon-reload
sudo systemctl restart docker docker.service

这对我上面描述的所有情况都不适用。 - JSamir
它适用于所有情况! - Masih Jahangiri

-4
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

3
你能否描述一下你的答案,而不是只粘贴一堆iptables命令? - Marc

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接