DEV Community

Cover image for Use Docker with Proxy Servers Tutorial
Manuel Castellin
Manuel Castellin

Posted on

Use Docker with Proxy Servers Tutorial

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!

Proxy settings for docker engine and containers

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:

docker pull fail

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 see localhost,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 ✅

docker desktop proxy settings

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/
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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”
Enter fullscreen mode Exit fullscreen mode

3) Save and close the file, and restart Docker with

> sudo systemctl restart docker.service
Enter fullscreen mode Exit fullscreen mode

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 \
    --env http_proxy="http://my.proxy.com:3128" \
    --env https_proxy="http://my.proxy.com:3128" \
    nginx sh -c "curl google.com"
Enter fullscreen mode Exit fullscreen mode

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! 🚀

Don't forget to follow me for more content like this!

Top comments (9)

Collapse
 
ajaykulkarn profile image
Ajay Kulkarni

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?

Collapse
 
mcastellin profile image
Manuel Castellin

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 🙂

Collapse
 
ajaykulkarn profile image
Ajay Kulkarni

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?

Thread Thread
 
mcastellin profile image
Manuel Castellin

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:

EnvironmentFile=/etc/docker/docker-proxy.env
Enter fullscreen mode Exit fullscreen mode

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!

Collapse
 
igorello74 profile image
Igorello74

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

Collapse
 
manishfoodtechs profile image
manish srivastava

Nice 👏👏👏👏

Collapse
 
mcastellin profile image
Manuel Castellin

Thank you, Manish!

Collapse
 
aldobranti profile image
aldobranti

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

Collapse
 
mcastellin profile image
Manuel Castellin

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 🤞