【问题标题】:Use socks5 proxy from host for docker build使用来自主机的 socks5 代理进行 docker build
【发布时间】:2020-08-18 18:23:45
【问题描述】:

要构建某个图像,我需要创建一个隧道并让 docker 将此隧道用作 socks5 代理(也可以将代理用于 DNS)。

所以现在我有几个问题:

  1. 如何让 docker 使用主机上的代理?
  2. 如何让docker使用代理获取基础镜像?
  3. 如何让 docker 使用代理来执行 RUN 指令?
  4. 如何让 docker 使用代理进行 ADD 指令?

【问题讨论】:

    标签: docker proxy dns socks tunnel


    【解决方案1】:

    因为我花了一整天的时间研究这个,这里是答案。

    我将在下面留下部分不完整/错误/旧的答案,因为我今天设置了一个新系统并且需要再次找出所有问题,因为旧答案的某些部分不再有意义。

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

    2. 也适用于 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": ""
                }
            }
        }
    
    1. 似乎ADD命令是用宿主机的(代理)环境变量执行的,忽略了config.json中的那些。更复杂的是,由于守护进程通常与root 用户一起运行,因此只获取root 用户的环境变量。更复杂的是,主机当然需要使用 localhost 作为代理主机。最重要的是:无论出于何种原因,在这种情况下,协议都需要为socks5(最后缺少h)。

    就我而言,由于我切换到 WSL2 并在 WSL2 中使用 docker(手动启动 dockerd docker 守护程序),我只需在调用 dockerd 之前导出所需的环境变量:

    #!/bin/bash
    DOCKER_DIR=~/sys/docker
    DOCKER_SOCK="$DOCKER_DIR/docker.sock"
    
    # unset any proxy env vars that the regular user might have set
    # because we pass the environment variables with sudo -E
    unset http_proxy
    unset https_proxy
    unset no_proxy
    unset HTTP_PROXY
    unset HTTPS_PROXY
    unset NO_PROXY
    # only this env var is needed for ADD in Dockerfile
    export http_proxy=socks5://localhost:3128
    
    export DOCKER_HOST="unix://$DOCKER_SOCK"
    if [ ! -S "$DOCKER_SOCK" ]; then
        mkdir -pm o=,ug=rwx "$DOCKER_DIR"
        chgrp docker "$DOCKER_DIR"
        sh -c "nohup sudo -E -b dockerd < /dev/null > $DOCKER_DIR/dockerd.log 2>&1"
    fi
    

    如果您在 linux 机器上进行了“常规”设置,则可以使用 4. 的旧答案,但请注意您可能还需要使用 localhost。

    从这里开始的不完整/错误/旧答案

    1. 使用 localhost:port 不起作用。在this 问题解决之前,您需要使用 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. 我不知道为什么,但是对于 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 地址)。
    【解决方案2】:

    为了在本地连接一个容器到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"

    【讨论】:

      【解决方案3】:
      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
      

      【讨论】:

      • 你能描述一下你的答案,而不是仅仅粘贴一堆 iptables 命令吗?
      【解决方案4】:

      使用 localhost:port 通过在“docker build ...”命令中添加“--network=host”选项来工作。

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-15
      • 1970-01-01
      相关资源
      最近更新 更多