Set up nginx proxy for react application

12,659

Solution 1

I found the problem. In the multi-stage build of the docker image, I accidentally copied the nginx.conf file into the builder image, not the production one.

The fixed Dockerfile now looks like this:

# build environment
FROM node:11.13 as builder

RUN mkdir /usr/src/app
WORKDIR /usr/src/app

ENV PATH /usr/src/app/node_modules/.bin:$PATH

COPY package.json /usr/src/app/package.json
RUN npm install
RUN npm install [email protected] -g

COPY ./package-lock.json /usr/src/app/
COPY ./public /usr/src/app/public
COPY ./src /usr/src/app/src


RUN npm run build

# production environment
FROM nginx:1.15.10-alpine
COPY --from=builder /usr/src/app/build /var/www
COPY ./nginx.conf /etc/nginx/nginx.conf
CMD ["nginx", "-g", "daemon off;"]

and nginx.conf:

server {
    listen 80;
    include /etc/nginx/mime.types;
    root /var/www;
    index index.html index.htm;
    location /api {
        resolver 127.0.0.11;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Server $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass http://server:8080$request_uri;
    }
    location / {
        try_files $uri $uri/ =404;
    }
}

Solution 2

It works fine in dev because you have a webpack dev server proxying you requests to port 8080 ( the "proxy": "http://server:8080" line ), but this is gone in production builds.

Adding $request_url to you proxy_pass should fix it.

    location /api {
       proxy_set_header X-Forwarded-Host $host;
       proxy_set_header X-Forwarded-Server $host;
       proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
       proxy_pass http://server:8080$request_uri;
    }
Share:
12,659
fugasjunior
Author by

fugasjunior

Updated on June 09, 2022

Comments

  • fugasjunior
    fugasjunior almost 2 years

    I'm trying to create a docker-compose using two services, a Spring Boot backend (running on port 8080) and React frontend running on Nginx.

    The react app calls backend API like /api/tests. However, when I run the docker compose and frontend makes a request, it always fails with 404 error: GET http://localhost/api/tests 404 (Not Found)

    When I set the frontend dockerfile not to use Nginx, just npm start, it worked fine, but I would prefer using production build on Nginx.

    Current frontend dockerfile:

    FROM node:11.13 as builder
    
    RUN mkdir /usr/src/app
    WORKDIR /usr/src/app
    
    ENV PATH /usr/src/app/node_modules/.bin:$PATH
    
    COPY package.json /usr/src/app/package.json
    RUN npm install
    RUN npm install [email protected] -g
    
    COPY ./package-lock.json /usr/src/app/
    COPY ./public /usr/src/app/public
    COPY ./src /usr/src/app/src
    
    COPY ./nginx.conf /etc/nginx/nginx.conf
    
    RUN npm run build
    
    FROM nginx:1.15.10-alpine
    COPY --from=builder /usr/src/app/build /usr/share/nginx/html
    CMD ["nginx", "-g", "daemon off;"]
    

    Nginx.conf:

    server {
        listen 80;
    
        location / {
            try_files $uri $uri/ /index.html;
            add_header   Cache-Control public;
            expires      1d;
        }
    
        location /api {
           proxy_set_header X-Forwarded-Host $host;
           proxy_set_header X-Forwarded-Server $host;
           proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
           proxy_pass http://server:8080/;
        }
    }
    

    docker-compose:

    version: "3"
    
    services:
      server:
        build: test-server/
        expose:
          - 8080
        ports:
          - 8080:8080
      ui:
        build: test-ui/
        expose:
          - 80
        ports:
          - 80:80
    

    The react app has a line "proxy": "http://server:8080" in its package.json.

    Nginx logs the following error:

    2019/04/15 12:50:03 [error] 6#6: *1 open() "/usr/share/nginx/html/api/tests" failed (2: No such file or directory), client: 172.20.0.1, server: localhost, request: "GET /api/tests HTTP/1.1", host: "localhost", referrer: "http://localhost/"
    
  • fugasjunior
    fugasjunior about 5 years
    Now I can see why the config in package.json did not work, but unfortunately, I tried adding $request_uri to the proxy and it still fails.
  • fugasjunior
    fugasjunior about 5 years
    Is there a way to reference the API service using its name, like in this case server:8080? It worked when I tried running the dev server, but when I hardcoded it to server:8080/api/tests, it fails to resolve the name.
  • jay_aye_see_kay
    jay_aye_see_kay about 5 years
    That's weird I have an almost identical nginx.conf that's been working for me. The only other difference is that I have an upsteam statement at the top of my conf. Long shot but maybe try adding this to the top of the file ``` upstream server { server server:8080; } ``` And then change the proxy_pass line to ``` proxy_pass server$request_uri; ```
  • fugasjunior
    fugasjunior about 5 years
    Not working, unfortunately. Whenever I call the API, the server still tries to look into /usr/share/nginx/html/api/tests and fails doing so (No such file or directory). I guess I must be missing something in the conf file.