DEV Community

Shriharsh
Shriharsh

Posted on • Edited on

"Behind the Corporate Proxy"

Over the years, I have struggled to get past the corporate proxy, i.e. access to the internet was blocked because proxy details weren't set up properly. Usually, most software documentation wouldn't provide these details handy and one has search thru documentation. These are useless battles a developer has to fight in order to win the war.

Corporate Proxy!

I wish I could do what Liam Neeson does! But I have been able to win some of my battles and have accumulated some ammunition for a short post which might come handy to many in a similar situation. Here I list down some ways to set up proxy details in the following scenarios:

Running Vagrant behind the proxy

Set up the proxy in your guest OS

This depends on the guest OS. I use Ubuntu, so I find updating /etc/environment file with proxy details as an easy option.

    > cat /etc/environment 
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games"
    HTTP_PROXY=http://proxy_host:port
    HTTPS_PROXY=http://proxy_host:port
    FTP_PROXY=
    NO_PROXY=localhost,127.0.0.1
    http_proxy=http://proxy_host:port
    https_proxy=http://proxy_host:port
    ftp_proxy=
    no_proxy=localhost,127.0.0.1

Enter fullscreen mode Exit fullscreen mode

Use vagrant-proxyconf plugin

With this plugin, you can setup the proxy details right into the Vagrantfile. To install the plugin run the following command on your shell:

> vagrant plugin install vagrant-proxyconf
Enter fullscreen mode Exit fullscreen mode

If you are not able to download the plugin behind the corporate proxy (duh!), then you can download the gem file from Ruby Gems site and use the following command to install the plugin.

> vagrant plugin install /path/to/my-plugin.gem
Enter fullscreen mode Exit fullscreen mode

and add following to the Vagrantfile:

Vagrant.configure("2") do |config|
  if Vagrant.has_plugin?("vagrant-proxyconf")
    config.proxy.http     = "http://<your-proxy-host>:<port>/"
    config.proxy.https    = "http://<your-proxy-host>:<port>/"
    config.proxy.no_proxy = "localhost,127.0.0.1"
  end
  # ... other stuff
end
Enter fullscreen mode Exit fullscreen mode

Now you should be able to access the internet from your vagrant guest.1


Running Docker behind proxy

When you are working on docker behind the proxy, it becomes important that you ensure proxy settings are passed and are available at different stages - for example, image creation, container execution, and running services. There are different command options for either of these scenarios.

Setting proxy while building an image

You might want to download some software while building your image so that every container has it pre-installed. While you can hardcode the proxy details as environment variables in the Dockerfile, it isn't the recommended way of doing so. It hampers the portability of the image and unnecessarily gives the container created by the image access to the internet. The better option would be to pass the proxy information while building the image using build-arg option as shown below:

> http_proxy=<yourproxyserverhost>:<port>
> https_proxy=<yourproxyserverhost>:<port>
> docker build --build-arg http_proxy=$http_proxy --build-arg https_proxy=$https_proxy -t <your-image> .
Enter fullscreen mode Exit fullscreen mode

The build-arg option would allow you to pass a value to an environment variable defined in your Dockerfile using ARG instruction. However, it is a bit easier to pass proxy details. For proxy details, Dockerfile allows you to skip mentioning the proxy environment variable via ARG instruction in the Dockerfile.2

Setting up proxy when running the container

Again as mentioned above, it isn't advisable to setup proxy details in the image or to enter each new container to setup proxy details. Docker provides a better way to do so using the -e or --env options with the run command. This option can be used to pass the proxy setting as environment variables to the container.

> docker container run -e http_proxy nginx #..........................(1)
> docker container run -e https_proxy=<proxyhost:port nginx #.........(2)

Enter fullscreen mode Exit fullscreen mode

Notice the difference between two commands above. If http_proxy is already defined on the docker host, we can directly pass its value to the container by just passing the name of the variable to -e options as shown on line#(1) above. If you want to provide an alternate value you can pass name=value pair as shown in line#(2) above. Finally, you can also set up all the proxy variables in a file and use the --env-file option to pass all of them at once.

> cat all-proxy-vars.txt 

http_proxy=http://proxy_host:port
https_proxy=http://proxy_host:port
ftp_proxy=
no_proxy=localhost,127.0.0.1

> docker container run --env-file ./all-proxy-vars.txt nginx 
Enter fullscreen mode Exit fullscreen mode

Environment options on the Docker CLI commands offers quick way tweak and test an image. 3

Setup proxy for Docker Compose - The easiest thing.

While the steps described above will come handy when you are experimenting with your images and containers. Once you have finalized your container and image details, the best approach would be to create a compose file for your service which would build the image. Docker compose allows you to pass the environment details easily using the args instruction. You just need to mention the name of the proxy environment variables as shown below:

version: '2.3'

services: 
    ngnix-service:
        image: my-nginx-image
        build: 
            context: .
            args: # Environment variables available at build-time
                - http_proxy
                - https_proxy
                - no_proxy
        environment: # Environment variables available at container run-time
            - https_proxy
            - http_proxy
            - no_proxy
        volumes: 
.........
Enter fullscreen mode Exit fullscreen mode

As noted in the code snippet, environment variables defined as build > arg level are only available when image is being built. Whereas, environment level list of environment variable is available at container run-time.

So these are the corporate proxy battles that I have fought and won somehow. A long time back, I had a hard time getting thru an NTLM-based proxy. But a cool tool called CNTLM saved my day. However, I don't have the scenario or the steps handy to add to this article.

One thing is for sure, once you have resolved such issues, you can quickly identify a similar issue with a new software. I would add to this article when I fight and win more such battles. I hope you this post helps you save some time.


  1. Detailed instruction on Vagrant-proxyconf plugin can be found here. http://tmatilai.github.io/vagrant-proxyconf/  

  2. The official Docker documentation explains how to use build-args https://docs.docker.com/engine/reference/commandline/build/#set-build-time-variables-build-arg 

  3. Environment options on the Docker CLI commands. https://docs.docker.com/engine/reference/commandline/run/#set-environment-variables--e-env-env-file 

Top comments (1)

Collapse
 
juppwerner profile image
Jo Werner • Edited

Hello Shriharsrsh,

Thanks for this great article. I am also struggeling with HTTP proxies at many places :-(

At the section "Setting proxy while building an image", where you write:

docker build --build-arg http_proxy=$http_proxy --build-arg https_proxy=$https_proxy ...

...I noticed that my uppercase variable names from the WINDOWS environment keep uppercase in the MINGW docker shell. So I need to write the values in uppercase, too:

docker build --build-arg http_proxy=$HTTP_PROXY --build-arg https_proxy=$HTTP_PROXY ...

Or:

  • Edit the .bashrc
  • Add some lines to get the lower case variables copied:
export http_proxy=$HTTP_PROXY
export https_proxy=$HTTPS_PROXY
export no_proxy=$NO_PROXY

Then, running:

docker build --build-arg http_proxy --build-arg https_proxy ...

is sufficient.

Regards
Joachim