Deploy your React App using Docker and Nginx
Deploy your React App using Docker and Nginx
Hello reader, it's Sourab here. Recently in one of my projects I used Docker and Nginx for deploying a React App to a front-end server. Let's see how I did it.
First, we will need a React project so you can skip creating a new React project if you already have one.
Create a new React project and spin it up
npx create-react-app with-docker
cd with-docker
npm start
It will start your react app at port 3000 and open up in the browser with this interface below
Our app is running fine. So let's close it now and move to the next step.
Create a Dockerfile
In the root directory of your project, we will create a new file and name it Dockerfile. It will look something like this in your project directory
and add this code to that Dockerfile
#React app image
FROM node:lts-alpine as build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:lts-alpine as build will tell docker to download a slim LTS(Long Term Support) version of Node image from Docker Hub and set up a Node environment with all base requirements needed to run a Node project in our case a React project for production that.
WORKDIR /app will tell the docker that in that image we need a dedicated director i.e. /app where the whole project will sit. And whatever changes we make using the steps in this Dockerfile will only affect that /app directory nothing else.
COPY package*.json ./ will copy all the files having the prefix package and suffix .json into the working directory.
RUN npm ci will install all the packages specified in the package.json file of our project into the image.
COPY . . will copy the source directory in the working directory.
RUN npm run build will execute the npm run build script from package.json which will then generate a build directory and all our code will be minified, streamlined, and bundled together into static HTML, CSS, and JavaScript files. This build is highly compressed, optimized, and ready for production. We will use this build to serve.
Nginx Configuration
In the root directory of our project, we will create one file named nginx.conf and paste this code:
http {
include mime.types;
set_real_ip_from 0.0.0.0/0;
real_ip_recursive on;
real_ip_header X-Forward-For;
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;
server {
listen 80;
server_name localhost;
root /proxy;
limit_req zone=mylimit burst=70 nodelay;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri /index.html;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
}
events {}
Nginx will need this configuration to listen for any connection at port 80 and serve the contents of /usr/share/nginx/html. This configuration may change based on your requirements.
Update the Dockerfile for Nginx
For now, our Dockerfile is only going to build a React app image but we can also create another image for Nginx which will save us from manual setup of Nginx on any target machine and configure it for our app.
So open up the Dockerfile again and add these steps at the bottom of the file.
FROM nginx:latest as prod
COPY --from=build /app/build /usr/share/nginx/html
COPY nginx.conf /etc/nginx/nginx.conf
EXPOSE 80/tcp
CMD ["/usr/sbin/nginx", "-g", "daemon off;"]
FROM nginx:latest as prod gets the latest Nginx docker image and annotates it as prod for production usage.
COPY --from=build /app/build /usr/share/nginx/html from the build stage of the image copy the build directory contents from /app/build to /usr/share/nginx/html which is the default directory for Nginx to server html contents but it can be changed if needed.
COPY nginx.conf /etc/nginx/nginx.conf This will copy the nginx.conf file created earlier and replace the contents of the /etc/nginx/nginx.conf in the target machine.
EXPOSE 80/tcp exposes port 80 and listens for incoming connections and serves the React app.
CMD ["/usr/sbin/nginx", "-g", "daemon off;"] fire up the nginx server and keep it alive.
NOTE: These types of images where we have two different stages of builds (i.e. React app and Nginx) are called Multi-stage builds
Finally build a docker image and run the docker container
To build the docker image use this command
docker build -t with-docker:1.0.0-prod .
After the image build is complete run the container using this image with this command
docker run -d -p 80:80 --name react-server with-docker
Now your Nginx server is listening at port 80 and will serve your React app.
Thank you for reading. Peace out.