4

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 npm@2.15.5
npm info using node@v4.4.6
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" ]
Rubén
  • 34,714
  • 9
  • 70
  • 166
p.venkman
  • 59
  • 1
  • 1
  • 7

2 Answers2

6

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/

dlouzan
  • 675
  • 7
  • 16
  • This issue is very close to my situation (even though mine is pip instead of npm) but unfortunately this solution doesn't seem to work for me. I tried to put the proxy in the build-args, and tried to put it in the ENV, but neither of them worked. My port is not 3128 though because it was used by something else (not clear what), so I am using 8080 instead. Another issue that I suspect is related: https://stackoverflow.com/q/53510864/5122657 Do you have any other idea? – Leonard AB Nov 29 '18 at 07:02
  • Well it really depends on your setup. If you are using native docker for windows I know that in there with HyperV there's been network issues. I guess your best bet would be to open a new question documenting in detail your setup. – dlouzan Nov 29 '18 at 13:03
  • 1
    @dlouzan thank you for the reply. I finally managed to solve the problem. In my case it was not changing it into the `bridge` network, but instead to the `dockerNAT` IP itself. Not sure why it works that way though. I documented the detail [here](https://stackoverflow.com/a/53551452/5122657). – Leonard AB Nov 30 '18 at 05:09
  • FYI After facing the same issue and looking at DOZENS of posts including this one (whose solution seems mighty complicated) what worked was a simple proxy config to be passed to `npm` itself. This fixed it during the docker build process. All I had to do was add these lines to my Dockerfile BEFORE running the `npm install` command :- `RUN npm config set http-proxy http://:8099` and `RUN npm config set https-proxy http://:8099` – Lester Gray Jun 24 '22 at 17:44
  • @LesterGray Thanks for the hint! The original question was using CNTLM running in localhost as the proxy, which is a typical enterprise setup for devs if your company proxy uses NTLM authentication (yes, life can be so horrible). So the answer addresses it from that perspective. Using the proxy config only for npm has another disadvantage: it won't work in the general case, e.g. if your build performs some kind of curl, which the `http(s)_proxy` variables will honor. – dlouzan Mar 31 '23 at 16:07
0

Had the exact same situation! Just setting proxy and http-proxy in .npmrc like this worked for me.

proxy = http://your-company-proxy
https-proxy = http://your-company-proxy

Might also work if you run

RUN npm config set proxy http://your-company-proxy
RUN npm config set https-proxy http://your-company-proxy

in your Dockerfile.

Rinta
  • 71
  • 5