merry-go-round
merry-go-round

Reputation: 4625

"ECONNREFUSED" error after containering Node.js (Express)

I have node.js playing a role of "reverse proxy" which hides the main server (application).

It worked fine before I containerized but it gets me an error while npm install in Docker - reason: connect ECONNREFUSED 127.0.0.1:8080

Seems like ENV HTTP_PROXY "http://1270.0.1:8080" didn't work.

What might cause the problem? + How can I possibly fix this?

Dockerfile in for Node.js - Run command: docker build -t saml-enabled-reverse-proxy .;docker run -it -p 8446:8446 saml-enabled-reverse-proxy bash

FROM node:12.10.0

ENV HTTP_PROXY "http://127.0.0.1:8080"
ENV HTTPS_PROXY "https://127.0.0.1:8080"

# Create app directory

# Install app dependencies
# A wildcard is used to ensure both package.json AND package-lock.json are copied
# where available (npm@5+)
COPY package*.json ./

# RUN npm config set proxy http://127.0.0.1:8080
# RUN npm config set https-proxy http://127.0.0.1:8080
RUN npm config set proxy null
RUN npm config set https-proxy null
RUN npm config set registry https://registry.npmjs.org
RUN npm install
# If you are building your code for production
# RUN npm ci --only=production

COPY . .

EXPOSE 8080
EXPOSE 8446
CMD [ "node", "src/index.js" ]

Application Dockerfile port 8080 - application (hided by reverse proxy)

FROM ubuntu:16.04
...

ENV HTTP_PROXY "http://127.0.0.1:8446"
ENV HTTPS_PROXY "https://127.0.0.1:8446"

Upvotes: 2

Views: 1418

Answers (1)

hwkd
hwkd

Reputation: 2638

The Problem
From the container's point of view, 127.0.0.1 is the ip address of itself -- not the host OS. That means you shouldn't set 127.0.0.1:8080 as a HTTP_PROXY and HTTPS_PROXY because your container would be calling itself so it won't reach the Internet. This is why your npm install isn't working.

Similarly, your main application behind the node.js proxy should not be using

...
ENV HTTP_PROXY "http://127.0.0.1:8446"
ENV HTTPS_PROXY "https://127.0.0.1:8446"
...

because that would be calling itself at port 8446 and not the 8446 of the host OS (which you intended to route to the other container running the node.js proxy, but this will never work).

The Solution
You have to use something like docker compose or docker swarm to link the two containers' network. Refer to the following example docker-compose.yml:

version: "3.7"

services:
  proxy:
    image: myproxy
    port:
      - 8080:8080

  app:
    image: myapp

Also, remove the following lines from your proxy dockerfile and rebuild the image.

ENV HTTP_PROXY "http://127.0.0.1:8080"
ENV HTTPS_PROXY "https://127.0.0.1:8080"

Similarly, change the main application dockerfile from this

ENV HTTP_PROXY "http://127.0.0.1:8446"
ENV HTTPS_PROXY "https://127.0.0.1:8446"

to

ENV HTTP_PROXY "http://proxy:8446"
ENV HTTPS_PROXY "https://proxy:8446"

Now run docker-compose up with this configuration, and your main app will be able to reach proxy container by the host name proxy rather than 127.0.0.1. Which means that you will use proxy:8080 to use the proxy running on port 8080.

PS: You are able to route to the docker containers/services via their service name because docker has a service discovery mechanism it maintains internally and it will resolve the ip address of these conatiners dynamically. This is essential to containers because containers can be destroyed and recreated at any time which means that IP addresses can change at any time. In order to resolve this, docker maintains a key-value store which maps service/host names to the IP addresses of these containers and resolve them for containers that are trying to reach other containers. Make sure to change all the IP addresses within your app to use host/service names instead of static IP addresses if they should route to other docker containers/services.

Upvotes: 3

Related Questions