Dockerizing React Apps

ยท

6 min read

Featured on Hashnode

Containerized development is hot ๐Ÿ”ฅ What makes these tools so popular? From my experience, containers:

  • Make complex local environments quick and easy to spin up
  • Allow for specific versioning of languages and packages to coexist locally
  • Provide an easy tool to ship code for pipeline integration and deployment
  • Help create a consistent work environment across developers

Docker has taken the spotlight for creating development containers. This tutorial will show you how to dockerize a project created with Create React App.

Prerequisites

In order to go through this tutorial, you should have node (LTS version if you're uncertain) and docker installed. The links just listed should work for you, but feel free to use Homebrew or installer you prefer.

Project Startup

If you don't have a CRA project yet, use npm to create a new one using the npx command:

npx create-react-app my-project

Move into your project:

cd my-project

Start up and check out your app:

yarn start

It soon should be running at http://localhost:3000. When you've had your fun exploring, turn off the server when with ctrl+c and get ready to start dockerizing ๐Ÿค“

Dockerize!

New docker images are built on a base image and ours will be no different. Docker hub contains a multitude of images. It is probably no surprise that we will be using a node docker image as our base (we'll use 14.15.1 which is LTS at the time of writing).

To specify this docker image and other configuration, create the file Dockerfile in the root of your project and add the following:

# pull official base image
FROM node:lts-alpine

# set working directory
WORKDIR /app

# add `/app/node_modules/.bin` to $PATH
ENV PATH /app/node_modules/.bin:$PATH

# copies package.json and package-lock.json
COPY package*.json ./

# installs app dependencies
RUN npm install
RUN npm install react-scripts -g

# add app contents to the container
COPY . ./

# start app
CMD ["npm", "start"]

Let's break this down line by line

  1. FROM node:lts-alpine This line tells docker what base image to use. We want to use the latest stable (LTS stands for long term stable) version of node. Alpine is a distribution of linux that is designed for security, simplicity, and resource efficiency. It is a common choice for docker images because of this.
  2. WORKDIR /app It's good practice to chose a working directory to enter into. If you don't, docker will copy all the contents into the root of the image. If there is namespace clashes, there may be

Also, create a .dockerignore file in the root of your project with the following content:

node_modules
build
.dockerignore
Dockerfile
Dockerfile.prod

This makes sure not to copy any unnecessary files to our docker image.

Start Up Docker

First, we need to build the docker image:

docker build . -t local-react

The -t local-react is a tag to easily reference our docker container later. You can change local-react to whatever name you want, just make sure you change the next script as well!

You should see the steps from the above Dockerfile run. Then we can start up our docker server with this command:

docker run \
  -it \
  --rm \
  -v ${PWD}:/app \
  -v /app/node_modules \
  -p 3000:3000 \
  local-react

Let's go through what's happening here line by line

  1. docker run starts up the docker container
  2. -it runs the docker container in interactive mode so that the container remains open after it starts. As of react-scripts v3.4.1 this is now required).
  3. -v ${PWD}:/app creates a volume of your current working directory into the app directory. This way, when changes are made locally, they will be reflected in docker
  4. -v /app/node_modules is a workaround to ensure that we use the node_modules in the docker container rather than the node_modules locally
  5. -p 3000:3000 exposes the docker port 3000 on your localhost so you can view the app running
  6. local-react is the tag of the container we built

Boom ๐ŸŽ‰ With any luck you should be up and running!