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/"
Proxy Setup with Create-React-App All you have to do is add a proxy field to your package. json file, like shown below. "proxy": "http://localhost:3000", This line instructs the development server to proxy any unknown requests to your API server in development mode.
Nginx is an open source web server that can also serve as a reverse proxy. Apart from being used to host websites, it's also one of the most widely used reverse proxy and load balancing solutions.
Proxy servers can assist in redirecting requests to APIs without having to go via the browser's default request options, which helps to evade several cross-origin limitations. Second is fetching data from cross-origin APIs that don't support CORs in web browsers.
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;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With