Skip to content
Advertisement

Docker is not accepting proxy api server

i get the following error, when doing a docker-compose up. The app is running but cannot make any api post/get requests. The express server is using port 5000.

] [HPM] Error occurred while trying to proxy request /api/users/user from localhost:3000 to http://localhost:5000/ (ECONNREFUSED) (https://nodejs.org/api/errors.html#errors_common_system_errors)

enter image description here

Despite having the react proxy set up, the error persists.

setupProxy.js

const proxy = require('http-proxy-middleware');

module.exports = function(app) {
//   app.use(proxy('/auth/github', { target: 'http://localhost:3000/' }))
  app.use(proxy('/api/users/auth/github', { target: 'http://localhost:5000/' }))
  app.use(proxy('/api/users/', { target: 'http://localhost:5000/' }))
  app.use(proxy('/api/posts/', { target: 'http://localhost:5000/' }))
}

Dockerfile

FROM node:8.10.0-alpine
EXPOSE 3000
COPY . /home/app
WORKDIR /home/app
RUN npm install
CMD ["npm", "start"]

docker-compose.yml

# docker-compose.yml
version: "3"
services:
  app:
    build: .
    depends_on:
      - postgres
    ports:
      - "3000:3000"
      - "9229:9229"
  postgres:
    image: postgres:9.6.8-alpine
    expose:
      - 5432
    environment:
      POSTGRES_PASSWORD: postgres
      POSTGRES_USER: user
      POSTGRES_DB: db

enter image description here

package.json

{
  "name": "sequelize-demo",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo "Error: no test specified" && exit 1",
    "client": "cd ./client && npm start",
    "server": "nodemon app.js  --ignore client",
    "build": "echo 'hello build'",
    "start": "concurrently --kill-others   "npm run server" "npm run client""
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "async": "^2.6.1",
    "bcrypt": "^3.0.3",
    "body-parser": "^1.18.3",
    "concurrently": "^4.1.0",
    "cookie-parser": "^1.4.3",
    "cookie-session": "^2.0.0-beta.3",
    "cors": "^2.8.5",
    "crypto": "^1.0.1",
    "dotenv": "^6.2.0",
    "express": "^4.16.4",
    "express-flash": "0.0.2",
    "express-session": "^1.15.6",
    "jsonwebtoken": "^8.4.0",
    "morgan": "^1.9.1",
    "nodemailer": "^5.1.1",
    "nodemon": "^1.18.9",
    "passport": "^0.4.0",
    "passport-github": "^1.1.0",
    "passport-github2": "^0.1.11",
    "passport-jwt": "^4.0.0",
    "passport-local": "^1.0.0",
    "pg": "^7.8.0",
    "pg-hstore": "^2.3.2",
    "sequelize": "^4.42.0"
  }
}

Advertisement

Answer

I think that you need to change localhost:5000 to the name of your service in the docker-compose.yml. In this case, you’ll need to setup whatever server you have running on localhost:5000 in the compose file. Remember that your containers are running inside a Docker Network, so, they can’t access your localhost at the host machine.

In this example, you can see that I needed to set the PMA_HOST environment variable to the db service instead of a “normal host”. In the database configuration, on my source code, I also set up the host to the same db service and everything is working just great.

version: ‘3’

services:
  app:
    build: .
    ports:
      - 80:80
    depends_on:
      - db
  db:
    image: mariadb:10.0
    volumes:
      - db:/var/lib/mysql
    ports:
      - 3306:3306
    environment:
      MYSQL_ROOT_PASSWORD: 123
  phpmyadmin:
    image: phpmyadmin/phpmyadmin
    ports:
      - 8080:80
    environment:
      PMA_HOST: db
    depends_on:
      - db
volumes:
  db:

This is needed because, every time you run a new container, it will get a different IP into the new Docker Network. In this case, we would always need to check this new IP and set it in our code. Docker solves this by letting us attach the new host to an easy and immutable name, which in compose is the name of the service.

UPDATE: The network_mode approach

If you already have a service running on your localhost (eg: an API server) and you’re using docker for a new service which will interact with that API (eg: a web client UI) but, for some reason, you can’t or don’t want to setup the API on the docker-compose.yml file, you can change the network_mode and the environment HOST.

In this approach, you’ll have to map the port on the container to an unused port on the host.

So, lets say you have an API running on localhost:80 and you’re running a node server on docker on port 3000. If you don’t have anything running at localhost:3000, you could do the following:

spa:
   user: ${COMPOSE_UID}:${COMPOSE_GID}
   image: node:10-slim
   working_dir: /home/node/app
   environment:
      - HOST=0.0.0.0
   ports:
      - 3000:3000
   volumes:
      - ./:/home/node/app
   command: bash -c 'yarn install && yarn run dev'
   network_mode: "host"
Advertisement