- Published on
Dockerize a React.js app
Why Docker?
Docker is a tool1 for running your applications inside containers. Containers package all the dependencies and code your app needs to run into a single file, which will run the same way on any machine.
Developing apps today requires so much more than writing code. Multiple languages, frameworks, architectures, and discontinuous interfaces between tools for each lifecycle stage creates enormous complexity. Docker simplifies and accelerates your workflow, while giving developers the freedom to innovate with their choice of tools, application stacks, and deployment environments for each project.
Dockerizing a React App
In this post, we will dockerize a React application. We will setup Docker with auto-reloading for development setup and optimized multistage docker build for production deployment.
There are many advantages of using Docker. Right now Docker is the defacto standard of containerizing applications. It is easy to build, package, share, and ship applications with Docker. As Docker images are portable it is easy to deploy the application to any modern cloud provider.
Prerequisites
Fo this guide, you need a react project. You don’t need high-level knowledge of docker since this is a beginner's guide. You can follow the steps mentioned in this guide.
Step 1 - Create a React Project
Let's start by creating a React application. You can use your existing React project. For this blog post, I am creating a new React application with create-react-app.
npx create-react-app react-docker
Here I created a new React app named react-docker. Let's verify the app by running the npm start command inside the project directory.
npm start
It will start the app and we can verify by visiting http://localhost:3000 in the browser. The application should be running.
2. Write Dockerfile
Now let's create a Docker image for the React application. We need a Dockerfile to create Docker images. Let's create a file named Dockerfile in the root directory of the React application.
FROM node:latest
WORKDIR /app
COPY package.json ./
RUN npm install
COPY . .
CMD ["npm", "start"]
Using .dockerignore
In our application, the one thing we do not need in our image is the node_module folder. Why? Well in our dockerfile, we are running npm install in order to get access to all the dependencies in our application. This in itself will create a node_modules folder to image.
node_modules
Dockerfile
.git
3. Building our Image
Now to get our container up and running, we have to first run the build command. This command goes over every step we have defined in our dockerfile as you will see when you run it.
docker build -t my-react-app .
After building the docker images we can verfiy by running docker images command.
docker images
REPOSITORY TAGS IMAGE ID CREATED AT SIZE
my-react-app latest 651a032c68f2 3 minutes ago 613MB
4. Running the container
We can run the Docker image with the docker run command. Here we are mapping the system port 3000 to Docker container port 3000. We can verify if the application is running or not by visiting http://localhost:3000.
docker run -d -p 3000:3000 my-react-app
- -d: This runs your container in detached mode. Simply put, when you leave a terminal session, it keeps your container running still.
- -p: This is used to publish the port you would like your application to run on.
5. Optimized the image
We can't ship this docker image to the production as it is not optimized. We will be using multi-stage build to create the docker image. One stage to build the production files and the other stage to serve them.
FROM node as builder
WORKDIR /app
COPY package-lock.json ./
COPY package.json .
RUN npm install
COPY . ./
RUN npm run build
FROM nginx:alpine as server
COPY --from=build /app/build /usr/share/nginx/html
COPY nginx/nginx.conf /etc/nginx/conf.d/default.conf
We will use Nginx to serve the files. It will create a very lightweight image. From the builder stage, we need to copy the files of the build folder to the /usr/share/nginx/html folder. Nginx docker image uses this folder to serve the contents. Nginx docker image will use the port 80 to serve the files and auto expose that port.
We need to pass a custom Nginx configuration to the docker image. We will create an nginx folder in the project's root directory and create an nginx.conf file there.
server {
listen 80;
server_name _;
access_log /var/log/nginx/access.log;
root /usr/share/nginx/html;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
}
Let's build the image again by running the docker build command and verify the image size
docker images
REPOSITORY TAGS IMAGE ID CREATED AT SIZE
my-react-app latest 561b032168f2 2 minutes ago 201MB
Conclusion
In this post, we learnt how to dockerize our React applications and optimized the Image using multi-stage build. In order to learn about Docker Hub or AWS ECR, you can read further or check other posts.
