If you ever tried to run Docker in a corporate network then you know what I'm talking about. To prevent potential intrusions, infrastructure engineers force all internet traffic to go through proxy servers, sometimes making it extremely difficult to run even the simplest thing.
Why should you read this article?
With this tutorial, you'll learn everything there is to know on how to configure proxies for Docker engine and containers!
- configure proxy servers in Docker for Desktop
- configure proxy servers with Linux & Systemd
- use proxy servers with running containers
Let's get started! π
Quick refresher: what is a Proxy server?
A proxy server is simply a server that sits in between your machine and the Internet, that can interact with the outside of your network on your behalf.
The main reasons why you would want to use a Proxy are the following:
- To improve network performance by caching internet content
- As an additional layer of security by implementing additional encryption, protect against DoS attacks, blacklist dangerous sites, and much more
- For auditing and logging purposes, many companies need to track who and when access mission-critical systems
How Docker uses proxies
One thing that was very confusing for me at first, is that Docker daemon and Docker containers don't share the same proxy configuration!
Settings for Docker engine
Your Docker engine needs to connect to the internet to access image registries and pull/push container images.
If your settings are not correct you will typically see errors when trying to use docker login
or pulling images from DockerHub, see below for example:
Setting a Proxy on Docker for Mac/Windows
If you're running Docker for Desktop this is a really simple operation. You can do this from Docker's settings Docker > Preferences > Resources > Proxies
. All you need to do is provide values for the following variables:
-
HTTP_PROXY
: the proxy server endpoint to handle HTTP calls -
HTTPS_PROXY
: the endpoint to handle HTTPS calls (notice this doesn't have to be an https endpoint) -
NO_PROXY
: a list of hosts that Docker can reach without using the proxy (usually you'll seelocalhost,127.0.0.1
in this field
After this, you should click the Apply & Restart button, and you'll be able to push/pull images β
Using authentication
One question I get asked a lot is how to provide authentication if this form does not have a username and password field. I am not sure why they didn't include such fields in the configuration, but you can just use URL authentication like this:
http://<username>:<password>@my.proxy.com:3128/
Setting a Proxy on Linux with Systemd
If you're working with a Linux installation, you won't have access to some nice Preferences menu. In Linux, the Docker engine is configured as a system service with Systemd.
Let's dust off our System Administration skills! π¨π»βπ»
In most Linux distributions, Docker is configured as a service with Systemd. You can alter the service configuration by creating an override file. Follow these simple steps:
1) Edit the Docker service configuration with:
> sudo systemctl edit docker.service
Systemd will open (or create) the service override file with your default terminal editor.
2) Add or modify the service configuration to include proxy variables. Your service file should look like this:
[Service]
Environment=βHTTP_PROXY=http://10.0.1.60:3128β
Environment=βHTTPS_PROXY=http://10.0.1.60:3128β
Environment=βNO_PROXY=localhost,127.0.0.1β
3) Save and close the file, and restart Docker with
> sudo systemctl restart docker.service
Running containers with proxy settings
Now that you set up proxies for Docker engine, you need to understand that Docker will never share those settings with running containers! ππ»
If you want your containers to access the internet, you'll need to supply Proxy settings using environment variables like this for example:
> docker run </span>
--env http_proxy="http://my.proxy.com:3128" </span>
--env https_proxy="http://my.proxy.com:3128" </span>
nginx sh -c "curl google.com"
Full Step-By-Step Tutorial
Take a look at my video below to see everything I described in the article in a real environment!
In the video, I'll also explain how you can configure Docker to use proxy configuration for containers by default? This way you won't have to pass http_proxy
and https_proxy
variables every time.
Productivity? Yes, please! π
Top comments (9)
How do we programmatically set the proxy variables? We can create http_proxy.conf files and restart docker. But the password is visible in plain text in http_proxy.conf. Is there any way to avoid this?
Hi Ajay,
it's a really good question but I'm afraid I'm not the best person to answer it. I've tried to find a solution for this on a while back, but I could not find a solid approach that is valid anywhere.
I think if you want to set the value programmatically you need to look for the best practices of the specific infrastructure you are using to deploy your containers. For example, if you're using an orchestrator like Kubernetes you could use secrets to mount a bash script that sets your proxy variables.
Or if you're on Amazon ECS you could use Secretsmanager and read the value from a CloudFormation script to set the container ENV (this one I tried and it works).
Hope this helps π
Thanks Manuel. I am using plain docker to do docker pull and don't want the password in plaintext for dockerd. Any way to avoid this?
Mmm let me see.. did you have a look at the
EnvironmentFile
directive for systemd units?I remember I did something like this to configure Samba persistent mounts while having passwords in a file with read-access only for the root user.
You could extract Docker proxy settings variables in a file such as
/etc/docker/docker-proxy.env
and then use the following directive in your unit file:This article might also help you unix.stackexchange.com/questions/4...
Remember to lock down your environment file afterwards with
chmod 400 /etc/docker/docker-proxy.env
I don't have an environment to test this out at the moment, let me know if this works!
Hi, Manuel! Thank you for this article, I found pretty useful. I've got a question for you: do you know if there's a way to config already created docker containers to use proxy? I mean that if I put proxy settings to config.json, those configs only apply to new containers. But the thing is that I already have a docker compose and a few containers running inside it, so I'd like to make them use my proxy.
Thank you
Nice ππππ
Thank you, Manish!
Hi
I arrived here because I just cannot pull anything from docker hub ,
never had to use a proxy before ... so is the host at 10.0.1.60 freely accessible ? do I need to find another ? and if so, where ?
but I went ahead and used the service override as you indicate. I was greatly surprised when this actuallyy succeeded in pulling "docker run -d -p 80:80 docker/getting-started"
I then tried "docker run hello-world" and I'm back to misery
docker: Error response from daemon: Get "registry-1.docker.io/v2/": net/http: TLS handshake timeout
Hi Aldobranti,
That IP address you see in the example
10.0.1.60
is a private internal IP in my network, you won't be able to use it as your proxy server.If you're not sure whether you should use a proxy or not to reach Docker Hub I suggest that you check with your network admin π This issue you're describing seems more of a connectivity issue though. Hope you manage to sort it out π€