Use socks5 proxy from host for docker build
Asked Answered
H

5

20

To build a certain image I need to create a tunnel and make docker use this tunnel as a socks5 proxy (to use the proxy for DNS too).

So now i've got several problems:

  1. How to make docker use the proxy that is on the host?
  2. How to make docker use the proxy to get the base image?
  3. How to make docker use the proxy for the RUN instruction?
  4. How to make docker use the proxy for the ADD instruction?
Hardenberg answered 4/5, 2020 at 10:41 Comment(0)
H
37

Since I spent all day researching this, here are the answers.

I will leave the partially incomplete/wrong/old answer below, since I set up a new system today and needed to figure out all of the questions again because some parts of the old answer didn't make sense anymore.

  1. Using localhost:port does not work. Until this issue is resolved, you need to use the IP address of your docker0 network interface (172.17.0.1 in my case). If your host OS is linux, you can use localhost:port by passing additional --network=host parameter to docker build as mentioned in some other answer.

  2. and 3. Just put this content (change IP and port if needed) into ~/.docker/config.json (notice that the protocol is 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. It seems that the ADD command is executed with the (proxy) environment variables of the host, ignoring those in config.json. To make things more complicated, since the daemon is usually running with the root user, only root user's environment variables are picked up. Even more complicated because the host of course needs to use localhost as host for the proxy. And the cherry on top: the protocol needs to be socks5 (missing the h at the end) in this case for whatever reason.

In my case, since I switched to WSL2 and use docker within WSL2 (starting the dockerd docker daemon manually), I just export the needed environment variable before the call to 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

If you have the "regular" setup on a linux machine, you could use the old answer to 4., but beware the probably there you also need to use localhost.

Incomplete/wrong/old answer starting here

  1. Using localhost:port does not work. Until this issue is resolved, you need to use the IP address of your docker0 network interface (172.17.0.1 in my case).
  2. This answer applies to question 3 too. Just put this content (change IP and port if needed) into ~/.docker/config.json (notice that the protocol is socks5h)
    {
        "proxies":
        {
            "default":
            {
                "httpProxy": "socks5h://172.17.0.1:3128",
                "httpsProxy": "socks5h://172.17.0.1:3128",
                "noProxy": ""
            }
        }
    }
  1. I do not know why (edit: now I know, it's because dockerd is running as root and it does not pick up proxy environment variables from the regular user), but for the ADD instruction the former settings to not apply (names do not get resolved through proxy). We need to put this content into /etc/systemd/system/docker.service.d/http-proxy.conf
[Service]
Environment="HTTP_PROXY=socks5://172.17.0.1:3128/"

then

sudo systemctl daemon-reload
sudo systemctl restart docker

(This is just wrong/unneeded with answer 2.)Also, for package managers like yum to be able to update the packages during build, you need to pass the environment variable like this:

docker build --build-arg http_proxy=socks5://172.17.0.1:3128
Hardenberg answered 4/5, 2020 at 10:41 Comment(3)
Have you tried to add a dummy net device to solve the problem of docker containers not 'seeing' the host. Would mean using a fixed 169.254.X.X type address, and will always be the same regardless of docker config in /etc/docker/daemon.json (default-address-pools settings could change that 172.17 address).Forlini
For all those who might be confused about the location of config.json and where to put it, just create it beside your Dockerfile, and in that Dockerfile set the DOCKER_CONFIG env with this name, eg : ENV DOCKER_CONFIG=config.jsonPachalic
@ImanHajimostafazadeh I think it is still easier to create this file either in .docker/ or even better .config/docker/ folder in your user's home directory.Hardenberg
A
5

Keep it simple

Create or edit the /etc/systemd/system/docker.service.d/proxy.conf file and add:

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

Replace <PROXY_PORT> with your proxy port. Then, reload systemd and restart Docker:

sudo systemctl daemon-reload
sudo systemctl restart docker docker.service
Acme answered 8/7, 2023 at 14:31 Comment(1)
It works for all cases!Acme
S
1

Using localhost:port works by adding "--network=host" option in "docker build ..." command.

Saltcellar answered 18/2, 2021 at 7:8 Comment(1)
Supporte only on Linux docs.docker.com/network/hostAlcott
K
-1

In order to connect a container to socks5 locally, that is, the entire Internet goes to a proxy, the container must have access to the machine host.

To access machine hosting within Linux you must: put --network="host" in run command:

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"

for mac and windows users we using 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"

Kanzu answered 9/12, 2021 at 8:57 Comment(1)
not working at all.Canaan
W
-5
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
Weatherford answered 20/3, 2021 at 16:40 Comment(1)
Can you describe your answer instead of just paste a bunch of iptables commands?Which

© 2022 - 2024 — McMap. All rights reserved.