React + Docker + Nginx - reactjs

I have some problem with create-react-app and docker configuration with nginx, this is my first time when i trying to dockerize react app. I tried many different settings and almost always i get 404 after build.
This is my docker file:
FROM node:alpine as build
WORKDIR /app
COPY package*.json /app/
RUN yarn install
COPY . .
RUN yarn run build
FROM nginx:alpine
COPY --from=build /app/build /usr/share/nginx.html
RUN rm /etc/nginx/conf.d/default.conf
COPY nginx/nginx.conf /etc/nginx/conf.d
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
Right now my nginx file looks like that, but as i said, i tried many different settings
server {
listen 80;
location / {
root /var/www;
index index.html index.htm;
try_files $uri $uri/ /index.html =404;
}
}
And this is what i see after build
I dont know if this is important but for routing i using react-navi.
Any ideas?

It looks like your Nginx configuration is looking at /var/www but you're copying your files to /usr/share/nginx.html. Shouldn't the copy command look like this?
COPY --from=build /app/build /var/www

Related

Unexpected Token Error in React When Hosting on a Subpath Using Nginx + Traefik

I have a Docker container running a production React app alongside Nginx for hosting its static files.
Dockerfile
FROM node:16.5.0-alpine AS builder
WORKDIR /app
COPY . .
ENV PUBLIC_URL /trade-journal
RUN npm ci --production
RUN npm run build
FROM nginx:1.23.1-alpine AS production
ENV NODE_ENV production
COPY --from=builder /app/build /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
nginx.conf
server {
listen 80;
location / {
# static file hosting location
root /usr/share/nginx/html/;
include /etc/nginx/mime.types;
try_files $uri $uri/ /index.html;
}
}
Above, you can see that I'm setting a PUBLIC_URL environment variable. This is because I'd like the app to be hosted on a subpath, like this: domain.com/trade-journal. I'm using Traefik to route to this subpath because in the future, I'd like to add more subpaths for other apps.
docker-compose.yml
reverse-proxy:
image: traefik:v2.8
command: --api.insecure=true --providers.docker
ports:
- "80:80"
- "8080:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
labels:
- traefik.enable=false
frontend:
build:
context: ./trade-journal/client
dockerfile: ./Dockerfile
image: "trade-journal-client"
labels:
- traefik.http.routers.frontend.rule=Host(`[MY-PUBLIC-IP-HERE]`) && PathPrefix(`/trade-journal`)
- traefik.http.services.frontend.loadbalancer.server.port=80
links:
- "backend:be"
I understand that React is designed to run on root by default, so I added:
<base href="%PUBLIC_URL%/"> in public/index.html, and
basename={process.env.PUBLIC_URL} to BrowserRouter
I've also alternatively tried setting the subpath with homepage in package.json, and writing the basename as just /trade-journal.
Either way, I get the same error in my browser on a blank page:
For whatever reason, it can't load http://domain/trade-journal/static/js/main.93967f03.js. Actually, I can't even view the code in that file, or any other JS or CSS files in that directory through the browser (even though I can when I bin/sh into the running container); I only ever get a blank index file.
I assume that the problem has to do with routing because when I remove any having to do with the subpath and host on /, the React app loads correctly.
I'm very new to hosting and deploying. How can I solve this problem?
It seems that I fixed it. I needed to use alias, and include the subpath in nginx as well. Now, I'm going to see if I can make this solution any more DRY (so I don't have to repeat the subpath so many times). If anyone has any suggestions, let me know.
location /trade-journal {
# static file hosting location
alias /usr/share/nginx/html/;
include /etc/nginx/mime.types;
try_files $uri $uri/ /trade-journal/index.html;
}

nginx:alpine config not correctly work with dockerimage

I want to host my angular app in my local browser.
This is my docker file configuration:-
FROM node:10.13.0-alpine as builder
WORKDIR /usr/src/app
COPY package.json package-lock.json ./
RUN npm cache clean --force
COPY . ./
RUN npm install
RUN npm run build --prod
FROM nginx:alpine
COPY --from=builder /usr/src/app /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
Now I try to build image and run it on localhost:8080 :-
PS C:\github_programming\ASP.NET and Angular\QuizQuestion\Fornted> docker run --name quizquestion1 -d -p 8080:80 quizequstion
005fd1a397f38c54675b24be1a502b32edadc5f653bcda8bee07b62c4448b3a7
I am only able to see only nginx welcome page.
If I browse http://localhost:8080/quiz:-
But it is working with npm start:-
I have little confused what I have missed here.
I do this exercise after I get a suggestion from Mr.Dave Maze
It shows lots of unwanted folder.So, I change the following in my docker file:-
FROM nginx:alpine
COPY --from=builder /usr/src/app/dist /usr/share/nginx/html
now folder structure like that:-
But it doesn't work, I am not getting desired result.
http://localhost:4000/quiz
PS C:\github_programming\ASP.NET and Angular\QuizQuestion\Fornted>
Docker run command:-
docker run --name quizquestion4 -d -p 4000:80 quizequstion
22ac476a121d221808415a2f59c6f511e765fd7d5325c03b9ff320905e0cd02c.
yup it working fine without docker.
Things I have noticed:-
If I have changed the app-routing.modules like that:-`
{ path: '', component: QuizComponent},
{ path: 'quiz', component: QuizComponent},
{ path: 'question', component: QuestionComponent },
{ path: 'question/:quizId', component: QuestionComponent },
{ path: 'register', component: RegisterComponent },
{ path: 'login', component: LoginComponent},
{ path: 'customer-list', component: CustomerListComponent},
Then I create new docker image and rebuild it.
I run it on port on http://localhost:4001:- I can see the quiz form
But routing http://localhost:4001/quiz doesn't work. It gives me 404 not found.
Yes locally, without dockerimage it is working:-
So for angular routing do I need to do any additions things to make docker image.
I tag angular js for that.
I think I missed something in docker build.
Any suggestion regarding this.
Thank you
for docker container if you did not specific any host it will launch on the docker container ip.
you can get this by (below) and get the IPAddress (lots of other good info there too!)
docker inspect <container id>
if you just want the IPAddress:
docker inspect <container id> | grep "IPAddress"
https://docs.docker.com/config/containers/container-networking/
By default, the container is assigned an IP address for every Docker
network it connects to. The IP address is assigned from the pool
assigned to the network, so the Docker daemon effectively acts as a
DHCP server for each container. Each network also has a default subnet
mask and gateway.
Finally I found the solution:-
So, I change the dockerfile content:-
FROM node:10.13.0-alpine as builder
WORKDIR /usr/src/app
COPY package.json package-lock.json ./
RUN npm cache clean --force
COPY . ./
RUN npm install
RUN npm run build --prod
# FROM nginx:alpine
# COPY --from=builder /usr/src/app/dist /usr/share/nginx/html
# EXPOSE 80
# CMD ["nginx", "-g", "daemon off;"]
FROM nginx:1.15.8
EXPOSE 80
COPY conf/default.conf /etc/nginx/conf.d/
RUN rm -rf /usr/share/nginx/html/*
COPY --from=builder /usr/src/app/dist /usr/share/nginx/html
CMD ["nginx", "-g", "daemon off;"]
Also we need to create Nginx configuration file in the project folder.
like that:-
Code for configuration file:-
server {
listen 80;
sendfile on;
default_type application/octet-stream;
gzip on;
gzip_http_version 1.1;
gzip_disable "MSIE [1-6]\.";
gzip_min_length 1100;
gzip_vary on;
gzip_proxied expired no-cache no-store private auth;
gzip_types text/plain text/css application/json
application/javascript application/x-javascript text/xml application/xml
application/xml+rss text/javascript;
gzip_comp_level 9;
root /usr/share/nginx/html;
location / {
try_files $uri $uri/ /index.html =404;
}
}
See help :- https://javascript.plainenglish.io/angular-10-on-docker-to-production-61ee6e84006
Thanks to all contributor for this post

react docker nginx kubernetes 404

::: UPDATE :::
It seems to be a SSL issue. I changed the nginx.conf to port 80 and it works.
I am trying to solve the problem of the 404 errors in React when a user clicks refresh.
The application runs in Docker in Kubernetes on Azure.
I have tried changing the nginx.conf file and pulling it into the container.
Even though the Docker builds, it seems like the container is still running the default nginx.conf.
nginx.conf
server {
listen 443 ssl;
location / {
root /var/www;
index index.html index.htm;
try_files $uri $uri/ /index.html?$args;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /var/www;
}
}
Docker file
FROM node:13.12.0-alpine as build
WORKDIR /app
ENV PATH /app/node_modules/.bin:$PATH
COPY package.json ./
COPY package-lock.json ./
RUN npm install
RUN npm install react-scripts#3.4.1 -g
COPY . ./
RUN npm run build
# production environment
FROM nginx:alpine
# copy the build folder from react to the root of nginx (www)
COPY --from=build /app/build /var/www
# --------- only for those using react router ----------
# if you are using react router
# you need to overwrite the default nginx configurations
# remove default nginx configuration file
RUN rm /etc/nginx/conf.d/default.conf
# replace with custom one
COPY /nginx/nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 443
CMD ["nginx", "-g", "daemon off;"]
Project Structure

React app deployed with docker and nginx : /etc/nginx/conf.d/default.conf differs from the packages

hi I am having a problem to deploy my React app ( create react app) using docker and nginx
the image is created with success : using the following script :
docker build -t front --network=host .
howver when I try to run the container : docker run -p 3000:80 front
it is not working and I got the following message :
10-listen-on-ipv6-by-default.sh: /etc/nginx/conf.d/default.conf differs from the packages version, exiting
my docker file :
FROM node:12.19.0-alpine3.12 as build
# set working directory
WORKDIR /app
# add `/app/node_modules/.bin` to $PATH
ENV PATH /app/node_modules/.bin:$PATH
#ARG REACT_APP_BACKENDURL
#ENV REACT_APP_BACKENDURL $REACT_APP_BACKENDURL
# install and cache app dependencies
COPY package.json ./
COPY package-lock.json ./
RUN npm ci
RUN npm install react-scripts#3.2.0 -g --silent
COPY . ./
RUN npm run build
# add app
#COPY . /app
# generate build
#RUN npm run build
############
### test ###
############
# base image
FROM nginx:1.19.0-alpine
# copy artifact build from the 'build environment'
COPY --from=build /app/build /usr/share/nginx/html
#nginx config with react router
COPY nginx/nginx.conf /etc/nginx/conf.d/default.conf
# expose port 80
EXPOSE 80
#COPY .env /usr/share/nginx/html
# run nginx
CMD ["nginx", "-g", "daemon off;"]
my nginx.conf :
server {
listen 3000;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
any ideas what I did wrong,, also I am looking for best practices to deploy REACT APP with docker
You should separate dockefile above into 2 dockerfile,
One for front image , one for nginx.
Then create both images. And 2 containers are belong to those images.
Expose dockerfile nodejs : 3000
And add to nginx configuration file: proxy_pass ip_address_nodejs_container:3000

deploy react app to GCP and multi ingress not working

I've been trying to setup a configuration where an Ingress on GCP is linking to two different backends
(so [public-ip]/backend1 for service1 and [public-ip]/backend2 for service2) but it doesn't seem to be working. The react app i'm deploying has this as nginx.conf configuration (shamelessly stolen from internet, I suspect this is what's not working properly)
server {
listen 80;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
It seems that for some reason it finds the index.html properly but not the javascript and css files that are generated with npm run build.
This is my Dockerfile
FROM node:alpine as build
WORKDIR /app
COPY . /app
ENV PATH /app/node_modules/.bin:$PATH
RUN yarn
RUN yarn build
FROM nginx:alpine
# copy the build folder from react to the root of nginx
COPY --from=build /app/build /usr/share/nginx/html
RUN rm /etc/nginx/conf.d/default.conf
COPY nginx/nginx.conf /etc/nginx/conf.d
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

Resources