Reputation: 741
I am making a React front-end application, and my aim is to serve the final (npm run build
) version using a Docker image, which contains a multi-stage build with my the source code and Nginx. There multiple other Dockerized services involved, and Traefik acts as the load balancer / forwarder / whatever else Traefik does.
Now here's the thing: When I build the image it works fine as long as Traefik is not involved and I'm simply forwarding the application to a port in my docker-compose.yml
file as follows:
version: '2.4'
services:
ui:
ports:
- someport:80
By doing this, I find the application served at http://address:someport
no problem.
Now what I eventually have to do is give the application a PathPrefix, and Traefik is a good tool for this. Say I want to eventually find the application from http://address/app
.
From what I understand, this is easily done in the docker-compose.yml
file using labels, like:
version: '2.4'
services:
ui:
ports:
- 80
labels:
- traefik.enable=true
- traefik.http.routers.myapp.rule=PathPrefix("/app")
- traefik.http.routers.myapp.entrypoints=web
Please notify me if these labels are insufficient for what I want to achieve!
So after launching my application and navigating to http://address/app
, nothing is rendered. Important! -> By looking at the console, it seems that the application is trying to access http://address/static/css...
and http://address/static/js...
source files and does not find them. There is nothing behind these addresses, but by adding /app
in between like http://address/app/static...
, the source files would be found like the are supposed to. How do I get my application to do this?
Is this a Traefik issue or an Nginx issue, or perhaps related to npm, which I find unlikely?
The Dockerfile for the as somewhat like:
# build env
FROM node:13.12.0-alpine as build
WORKDIR /app
ENV PATH /app/node_modules/.bin:$PATH
COPY package*.json ./
RUN npm ci
COPY . ./
RUN npm run build
# production env
FROM nginx:stable-alpine
COPY --from=build /app/build /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
Upvotes: 3
Views: 3290
Reputation: 11
For example in Next.js, I had to create next.config.js with content:
{
module.exports = {
basePath: '/nextjs',
}
where nextjs is my PathPrefix value from traefik.
Upvotes: 1
Reputation: 3881
I think what you're missing is that you need to let React know that it is not hosted at the root /
but a sub-path. In order to configure a different path and thus enabling React to properly build the paths to also access the assets such as CSS and JS, you need to set the "homepage"
key in your package.json
to a different value, for example,
"homepage": "http://address/app",
You can read more on the topic in the deployment section of the React docs.
Upvotes: 2
Reputation: 111
This is an interesting problem we had a couple days ago as well. I'll share what I found in the hopes that it points you in some form of right direction.
Using PathPrefix only, the application has to fully listen on the prefix. From https://docs.traefik.io/routing/routers/#rule
Since the path is forwarded as-is, your service is expected to listen on /products.
There is a Middleware that strips out prefixes should your app not listen on the subpath: https://docs.traefik.io/middlewares/stripprefix/ However the caveat there is
If your backend is serving assets (e.g., images or Javascript files), chances are it must return properly constructed relative URLs.
We haven't quite found solutions yet, other than changing the paths in our applications. But maaaybe this helps
Upvotes: 1