Home > Back-end >  Nginx not targeting the good port for the api
Nginx not targeting the good port for the api

Time:10-27

I'm trying to Dockerize a classic NodeJS (Express, TS) Angular application using nginx, but I struggle binding correctly my api throught nginx.

In fact, it seems that nginx target my localhost:80...

enter image description here

...while I want it to target my localhost:3000. When I manually ping that url while adding :3000 after localhost, it works.

I'm trying to keep my code simple. Here are my different files.

Back Dockerfile :

FROM node:15.14-alpine AS build

RUN mkdir -p /build/tmp
WORKDIR /build/tmp

COPY . .
RUN npm ci

CMD ["npm", "run", "start"]

Front Dockerfile :

### STAGE 1: Build ###
FROM node:15.14-alpine AS build
WORKDIR /usr/src/app
COPY package.json package-lock.json ./
RUN npm install
COPY . .
RUN npm run build

### STAGE 2: Run ###
FROM nginx:1.17.1-alpine
COPY nginx.conf /etc/nginx/nginx.conf
COPY --from=build /usr/src/app/dist/front /usr/share/nginx/html

dockercompose.yml :

version: '3.4'

services:
  mymusicads-front:
    container_name: mymusicads-front
    build:
      context: ./front
      dockerfile: Dockerfile
    ports:
      - 80:80
    restart: on-failure
    depends_on:
      - mymusicads-api
    networks:
      - front-back

  mymusicads-api:
    container_name: mymusicads-api
    build:
      context: ./api
      dockerfile: Dockerfile
    ports:
      - 3000:3000
    networks:
      - front-back

networks:
  front-back:
    driver: bridge

nginx.conf :

events{}

http {
    include /etc/nginx/mime.types;

    upstream api {
      server 127.0.0.1:3000;
    }

    server {
      listen 80;
      server_name front;
      root /usr/share/nginx/html;
      index index.html;
      location / {
          try_files $uri $uri/ /index.html;
      }
    }

    server {
      listen 80;
      server_name api;

      location /api/ {
          proxy_pass http://localhost:3000/;
          proxy_redirect off;
      }
    }
}

Thanks !

EDIT : By checking the error, we can see we're obtaining my Angular index.html file as a response, instead of the JSON object my API should return, which may signify an proxying error. Seems like nginx is missing the location /api/ instruction, or maybe the whole server one.

CodePudding user response:

When you use multiple server blocks in your configuration, nginx chooses the server block to process your request by the HTTP Host header value. If it won't match any of the specified server names (or if the Host header is absent at all), the default server block will be used. You can specify the default server block explicitly using default_server flag for the listen directive. If you don't specify it explicitly, the very first server block listening on the specific port will be used. See the How nginx processes a request official documentation page or this answer for even more details.

Try this configuration instead:

events {}

http {
    include /etc/nginx/mime.types;
    server {
        listen 80;
        root /usr/share/nginx/html;
        index index.html;
        location / {
            try_files $uri $uri/ /index.html;
        }
        location /api/ {
            proxy_pass http://mymusicads-api:3000/;
            proxy_redirect off;
        }
    }
}

You don't need to expose the node.js port 3000 to the outer world, it is only mymusicads-front container that should have an access to that port. According to What is the difference between docker-compose ports vs expose SO thread your dockercompose.yml file should be something like

version: '3.4'

services:
  mymusicads-front:
    container_name: mymusicads-front
    build:
      context: ./front
      dockerfile: Dockerfile
    ports:
      - 80:80
    restart: on-failure
    depends_on:
      - mymusicads-api
    networks:
      - front-back

  mymusicads-api:
    container_name: mymusicads-api
    build:
      context: ./api
      dockerfile: Dockerfile
    expose:
      - 3000
    networks:
      - front-back

networks:
  front-back:
    driver: bridge
  • Related