Building a docker image for a node.js app fails behind proxy

p.venkman picture p.venkman · Jun 29, 2016 · Viewed 10.7k times · Source

I have an issue with npm during the docker build. I am behind a corporate proxy and have read about 30 articles (and stackoverflow posts) addressing similar issues. However I was still not able to overcome this.

I am able to "npm install" the project and fetch all necessary dependencies outside of the docker build process (but also using the proxy), but not during.

What I have tried so far:

  1. Using the proxy directly (along with hardcoded auth data) and also over CNTLM. The description below is when using CNTLM.
  2. Using the http repository as depicted below with strict_ssl false.

npm config set strict-ssl=false \

npm config set registry=http://registry.npmjs.org/ \

  1. Passing the proxy settings as --build-arg, env and via the RUN param

  2. Starting with a clean git checkout (without node_modules) and after running the npm install

I am trying to build with:

$ sudo docker build --build-arg HTTP_PROXY=http://127.0.0.1:3128 --build-arg HTTPS_PROXY=http://127.0.0.1:3128 .

The output

Sending build context to Docker daemon 226.6 MB
Step 1 : FROM node:argon
 ---> c74c117ed521
Step 2 : ENV http_proxy http://127.0.0.1:3128/
 ---> Using cache
 ---> ad2e2df7429b
Step 3 : ENV https_proxy http://127.0.0.1:3128/
 ---> Using cache
 ---> 75fb2eb0bb22
Step 4 : RUN mkdir -p /usr/src/app
 ---> Using cache
 ---> ee79de37d6d7
Step 5 : WORKDIR /usr/src/app
 ---> Using cache
 ---> 404356f5def0
Step 6 : COPY package.json /usr/src/app/
 ---> Using cache
 ---> a2ec47267628
Step 7 : RUN git config --global http.proxy http://127.0.0.1:3128/
 ---> Running in 3cd5db8b1371
 ---> 7353cd94b67a
Removing intermediate container 3cd5db8b1371
Step 8 : RUN npm install
 ---> Running in 79ed0eb809d8
npm info it worked if it ends with ok
npm info using [email protected]
npm info using [email protected]
npm info preinstall app
npm info attempt registry request try #1 at 10:24:02 AM
npm http request GET https://registry.npmjs.org/bufferutil
npm info attempt registry request try #1 at 10:24:02 AM
npm http request GET https://registry.npmjs.org/connect-mongo
<snip>

npm info retry will retry, error on last attempt: Error: tunneling socket could not be established, cause=connect ECONNREFUSED 127.0.0.1:3128
npm info retry will retry, error on last attempt: Error: tunneling socket could not be established, cause=connect ECONNREFUSED 127.0.0.1:3128
<snip>

npm ERR! Linux 3.13.0-88-generic
npm ERR! argv "/usr/local/bin/node" "/usr/local/bin/npm" "install"
npm ERR! node v4.4.6
npm ERR! npm  v2.15.5
npm ERR! code ECONNRESET

npm ERR! network tunneling socket could not be established, cause=connect ECONNREFUSED 127.0.0.1:3128
npm ERR! network This is most likely not a problem with npm itself
npm ERR! network and is related to network connectivity.
npm ERR! network In most cases you are behind a proxy or have bad network settings.
npm ERR! network 
npm ERR! network If you are behind a proxy, please make sure that the
npm ERR! network 'proxy' config is set properly.  See: 'npm help config'

npm ERR! Please include the following file with any support request:
npm ERR!     /usr/src/app/npm-debug.log

This is my docker script

FROM node:argon

ENV http_proxy http://127.0.0.1:3128/
ENV https_proxy http://127.0.0.1:3128/

# Create app directory
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app

# Install app dependencies
COPY package.json /usr/src/app/

# setup proxies
RUN git config --global http.proxy http://127.0.0.1:3128/ && \
    npm config set strict-ssl=false \
    npm config set registry=http://registry.npmjs.org/ \
    npm config set proxy=http://127.0.0.1:3128/ && \
    npm config set https-proxy=http://127.0.0.1:3128/

# Install dependencies for node.js
RUN npm install

# Bundle app source
COPY . /usr/src/app

EXPOSE 8080
CMD [ "npm", "start" ]

Answer

dlouzan picture dlouzan · Aug 11, 2016

The approach using --build-arg is the correct one: you only want to use the proxy settings when building the Docker image, and not having them inside the Dockerfile so it is not tied to an specific environment (you don't need the ENV entries on it).

Your issue is that you are trying to use as cntlm proxy inside the docker build localhost, which is not valid since at build time it will point to the docker container running the build, but it should actually point to the address of your host offering cntlm in the docker network.

In order to make that work, you can configure your cntlm to listen in several interfaces, and then activate gateway mode so you can use it from other machines. This way, when your image is being built, you will send the requests from the docker instance to the host.

My docker bridge network is as follows (my host gets as address in docker0 172.17.0.1):

$ docker network inspect bridge
...
            "Config": [
            {
                "Subnet": "172.17.0.0/16",
                "Gateway": "172.17.0.1"
            }
...

In my cntlm.conf:

...
Listen          127.0.0.1:3128
Listen          172.17.0.1:3128
...
Gateway yes
Allow           127.0.0.1/32
Allow           172.17.0.0/16
Deny            0/0
...

With this config, cntlm will listen to both localhost and the docker bridge network, only allowing remote connections from any docker container.

You then use the proxy settings when building your image with npm:

$ docker build --build-arg=HTTP_PROXY=http://172.17.0.1:3128 --build-arg=HTTPS_PROXY=http://172.17.0.1:3128 .

I hope that helps, I know that making all of this in corporate networks is really a pita!

EDIT 18-aug-2016

Something I discovered today is, if you use docker-compose files with v2 format, starting the compose file will create a new network for your containers. This means that you need to adapt your cntlm file accordingly to accept connections from those new ranges.

As an example, one of my compose files has just created a network under 172.19.0.0/16, but my cntlm config only allowed connections from 172.17.0.0/16. Check your syslog to identify the issue if you experience connection problems.

https://docs.docker.com/compose/networking/