I have a reactjs app, and now I dockerized it with the following Dockerfile
# get the base node image
FROM node:alpine as builder
# set the working dir for container
WORKDIR /frontend
# copy the json file first
COPY ./package.json /frontend
# install npm dependencies
RUN yarn install
ENV REACT_APP_API_ADDRESS=http://localhost:7001
# copy other project files
COPY . .
# build the folder
RUN yarn build
# Handle Nginx
FROM nginx
COPY --from=builder /frontend/build /usr/share/nginx/html
COPY ./docker/nginx/default.conf /etc/nginx/conf.d/default.conf
and my nginx conf is simple like below:
server {
listen 7001;
server_name _;
index index.html;
root /usr/share/nginx/html;
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
location / {
try_files $uri /index.html =404;
}
}
and then, I build it and push it to docker hub, I hope if I have publish a new image or you can said the latest one, the reactjs application should popup a window or a notification to let the user click it (I can make it so far).
and then, if user click the update notification button, the another server i call it hook_upgrade_server in anther container, which will get a signal and then it will execute docker pull reactjs and restart it by docker run -d -p7001:7001 reactjs docker container with latest images.
Which mean, I want to install two container on the user host:
reactjs do some business
hook_upgrade_server for wait user click signal and pull latest image and restart
So, How can i make it happen?
Related
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;
}
Getting following error when deploying React app with service worker on nginx server with docker, the error cause service worker to be status: redundant
Here is my docker config
ARG ENV
WORKDIR '/app'
COPY . .
RUN ls -la
RUN yarn install
RUN yarn build:$ENV
FROM nginx:alpine
RUN apk add --no-cache bash
RUN apk add --no-cache ca-certificates
EXPOSE 80
COPY ./nginx/default.conf /etc/nginx/conf.d/default.conf
COPY --from=builder /app/build /usr/share/nginx/html
and nginx default.conf
server {
listen 80;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
location /healthz {
access_log off;
return 200 "healthy\n";
}
error_page 404 /index.html;
location = /index.html {
root /usr/share/nginx/html;
internal;
}
}
App runs fine when running ./build version locally with servo but only one deployment it shows above error and service worker no longer works.
::: 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
I am very new to Nginx and noticed that whenever I hit my server locally it logs. I was wondering, what config files do I need to create (and where do I put them) and what do I have to put into them to disable that behavior (I am trying to prevent spew). I am running my application on aws and am getting a lot of log lines of the form '172.31.22.19 - - [23/Jun/2021:23:38:33 +0000] "GET / HTTP/1.1" 200 3022 "-" "ELB-HealthChecker/2.0" "-"' Is there a way to disable that? Or do I need to disable everything?
My docker file is:
# pull official base image
FROM node:16 AS builder
# set working directory
WORKDIR /app
# install app dependencies
#copies package.json and package-lock.json to Docker environment
COPY package.json ./
# Installs all node packages
RUN npm install
# Copies everything over to Docker environment
COPY . ./
RUN npm run build
#Stage 2
#######################################
#pull the official nginx:1.19.0 base image
FROM nginx:1.19.0
#copies React to the container directory
# Set working directory to nginx resources directory
WORKDIR /usr/share/nginx/html
# Remove default nginx static resources
RUN rm -rf ./*
# Copies static resources from builder stage
COPY --from=builder /app/build .
EXPOSE 80
# Containers run nginx with global directives and daemon off
ENTRYPOINT ["nginx", "-g", "daemon off;"]
I can successfully run the above with 'docker run -p 80:80 my-app'
if you are using a docker run command to run the container then add the flag --log-driver none to the run command
Looking at your dockerfile youre running node and nginx in a single container. I would advise against this and seperate them into seperate containers using docker-compose
if you do this then add the line driver: none to the service running the nginx container
I fixed the issue by adding a nginx.conf file (see below) and changing the value of access_log to 'off'. I describe the steps I took
get the nginx.conf file:
Per What is the 'default' nginx.conf that comes with docker Nginx image? do the following:
# Create a temporary container
docker run -d --rm --name mynginx nginx
# Copy the nginx configuration in the container
docker cp mynginx:/etc/nginx .
create nginx.conf file in root of project. Mine was:
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log off;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
}
Modify Dockefile to (note the 'COPY nginx.conf /etc/nginx/nginx.conf'):
# pull official base image
FROM node:16 AS builder
# set working directory
WORKDIR /app
# install app dependencies
#copies package.json and package-lock.json to Docker environment
COPY package.json ./
# Installs all node packages
RUN npm install
# Copies everything over to Docker environment
COPY . ./
RUN npm run build
#Stage 2
#######################################
#pull the official nginx:1.19.0 base image
FROM nginx:1.19.0
COPY nginx.conf /etc/nginx/nginx.conf
#copies React to the container directory
# Set working directory to nginx resources directory
WORKDIR /usr/share/nginx/html
# Remove default nginx static resources
RUN rm -rf ./*
# Copies static resources from builder stage
COPY --from=builder /app/build .
EXPOSE 80
# Containers run nginx with global directives and daemon off
ENTRYPOINT ["nginx", "-g", "daemon off;"]
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