node.jsdocker-composemicroservicesexpress-gatewayhttp-status-code-502

Express-Gateway - 502 Bad Gateway with docker-compose Nodejs Microservices Architecture


I've been trying to do a NodeJS Microservices Architecture using Docker.

I currently have 2 services : Auth API et Users CRUD API. Now my goal is to setup a Gateway using Express-Gateway.

I followed many tutorials on the web to try to set it up but whenever I try to make a request to the gateway (acting like a proxy) it sends a 502 bad gateway response..

response error in PostMan

error in express-gateway logs

My docker-compose.yml :

networks:
  goodfood:
    driver: bridge

services:

  gateway:
    container_name: gateway
    image: 'node:17-alpine'
    # env_file:
    #   - ./gateway/.env
    working_dir: /usr/src/app
    volumes:
      - './gateway:/usr/src/app'
    command: npm run dev
    ports:
      - '8080:8080'
    networks:
      - goodfood

  auth:
    container_name: auth
    image: 'node:17-alpine'
    # env_file:
    #   - ./auth/.env
    working_dir: /usr/src/app
    volumes:
      - './auth:/usr/src/app'
    command: npm run dev
    ports:
      - '3002:3000'
    networks:
      - goodfood

  users:
    container_name: users
    image: 'node:17-alpine'
    env_file:
      - ./users/api/.env
    working_dir: /usr/src/app
    volumes:
      - './users/api:/usr/src/app'
    command: npm run dev
    ports:
      - '3001:3000'
    networks:
      - goodfood
    depends_on:
      - users-db

  users-db:
    container_name: users-db
    image: postgres
    restart: always
    env_file:
      - ./users/db/.env
    volumes:
      - './users/db/data:/var/lib/postgresql/data'
      - './users/db/scripts/init.sql:/docker-entrypoint-initdb.d/init.sql'
    ports:
      - '5432:5432'
    networks:
      - goodfood

  users-adminer:
    container_name: users-adminer
    restart: unless-stopped
    image: adminer
    ports:
      - '8181:8080'
    networks:
      - goodfood
    depends_on:
      - users-db

And my gateway.config.yml :

http:
  port: 8080
admin:
  port: 9876
  host: localhost

apiEndpoints:
  users:
    path: ['/users', '/users/*']
  auth:
    path: ['/auth', '/auth/*']

serviceEndpoints:
  users:
    url: 'http://users:3001'
  auth:
    url: 'http://auth:3002'

policies:
  - log
  - proxy
  # - jwt
  # - request-transformer

pipelines:
  authPipeline:
    apiEndpoints:
      - auth
    policies:
      - log:
          action:
            message: 'auth ${req.method}'
      - proxy:
          - action:
              serviceEndpoint: auth
              changeOrigin: true

  usersPipeline:
    apiEndpoints:
      - users
    policies:
      - log:
          action:
            message: 'users ${req.method}'
      - proxy:
          - action:
              serviceEndpoint: users
              changeOrigin: true
      # - jwt:
      #     action:
      #       secretOrPublicKey: 'goodfood'
      #       checkCredentialExistence: false
      # - request-transformer:
      #     action:
      #       body:
      #         add:
      #           user: req.user

If you need further details there's a github repo : https://github.com/KIVTVN/goodfood/tree/master


Solution

  • The problem lies in your gateway-config.xml file. It is not referring correctly to the ports defined in docker-compose.xml.

    The docker-compose.xml ports command is HOST:CONTAINER, so what the host refers to as 3001 for the users container, is port 3000 within the Docker. Express Gateway is running in Docker, so the service endpoints need to refer to the ports as they appear to other containers (they are distinguished by internal hostname as defined in the docker-compose.xml file rather than by port at this level):

    serviceEndpoints:
      users:
        url: http://users:3000
      auth:
        url: http://auth:3000
    

    If you want to hit these URLs from outside Docker, you'll need to specify the port (3001, 3002, etc).