dear stack overflow,
I’m trying to configure an Nginx reverse proxy to serve two react apps based on the base URL of each under the same domain, below you will find the current configuration used in the projects.
The current situation is that when browsing to the ADMIN URL (/admin/) the index.html
file is loaded for every single request that is done by the browser, so all the assets are loaded as if they are the index.html
, so my assumption is that the missing configuration is in one of the nginx.conf
files?
Project Structure
- NGINX (proxy)
- NGINX – React APP (/)
- NGINX – React APP Admin (/admin)
Configuration
Docker Compose
version: "3.7"
services:
nginx:
image: nginx:stable-alpine
container_name: nginx
ports:
- 8000:80
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
frontend:
container_name: frontend
build:
context: ../frontend
dockerfile: Dockerfile.prod
frontend-admin:
container_name: frontend-admin
build:
context: ../frontend-admin
dockerfile: Dockerfile.prod
nginx.conf
http {
server {
listen 80;
location /admin/ {
proxy_pass http://frontend-admin:80;
}
location / {
proxy_pass http://frontend:80;
}
}
}
REACT APPs
The files below are used in both projects, I have tried changing the ‘location /
‘ from the admin project to ‘location /admin/
‘ but without any success.
Dockerfile
# build environment
FROM node:14.16.1-alpine as build
WORKDIR /usr/src/app
COPY package.json yarn.lock ./
RUN yarn
COPY . ./
RUN yarn build
# production environment
FROM nginx:stable-alpine
RUN rm /etc/nginx/conf.d/default.conf
COPY --from=build /usr/src/app/dist /usr/share/nginx/html
COPY --from=build /usr/src/app/nginx.conf /etc/nginx/conf.d
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
nginx.conf
server {
listen 80;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html =404;
}
}
React APP
- Final URL should be: http://myapp.com/
- Base path:
vite.config.js
// ...
export default defineConfig(({ mode }) => ({
base: '/',
// ...
}));
React APP Admin
- Final URL should be: http://myapp.com/admin/
- Base path:
vite.config.js
// ...
export default defineConfig(({ mode }) => ({
base: '/admin/',
// ...
}));
2
Answers
What worked for me is to use
rewrite
on admin’s location block so the downstream nginx would receive clean paths.After some modifications, the global config looks like this:
While app configs look like this:
Then, requests are forwarded correctly to the admin nginx:
Also couple of things to notice:
/etc/nginx/mime.types
for all nginx to send the right Content-Types to the browser.default.conf
and addingnginx.conf
to/etc/nginx/conf.d
I directly replaced/etc/nginx/nginx.conf
nginx:latest
andnode:14.16.1
for building, but alpine should work just finedocker-compose.yml
Dockerfile.prod
better use sub domaines, this way you won’t have such issue, below an example I use for jenkins:
}
}