Dockerize React app for dev and prod
Tags: react, docker, container, dockercompose
Published: 2023-04-11 05:57:20

---
title: Dockerize React app for dev and prod
published: true
date: 2023-04-11 04:59:51 UTC
tags: react, docker, container, dockercompose
canonical_url: https://blog.vishnuprasaath.dev/dockerize-react-app-for-dev-and-prod
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l0itk6n5794ye9b4xr63.png
---

Okay, you have a frontend React app and you want to serve it via Docker. Let's do that!

In this wiki, we will dockerize both the development and production environment via separate Dockerfiles.

## Step 1: Project setup

Initialized a pretty standard react project using the default [create react app](https://github.com/facebook/create-react-app) (CRA) template. Or pick your existing React app. Below is the sample project folder structure.

```
 node_modules
 public
    favicon.ico
    index.html
    manifest.json
    robots.txt
 src
    App.css
    App.js
    index.css
    index.js
    logo.svg
 package.json
 yarn.lock

```

* * *

## Step 2: Init .dockerignore

Add a `.dockerignore` file, this will help us ignore `node_modules`, `.env` etc

```
.git
.gitignore
**/node_modules
**/npm-debug.log
build

```

* * *

## Step 3: Dockerize Development env

**Init Dockerfile**

Start by adding a `Dockerfile.dev`

```
FROM node:14-alpine AS development
ENV NODE_ENV development

# Add a work directory
WORKDIR /app

# Cache and Install dependencies
COPY package.json .
COPY yarn.lock .

#RUN yarn install
RUN npm i

# Copy app files
COPY . .

# Expose port
EXPOSE 3000

# Start the app
CMD ["yarn", "start"]

```

**Init docker-compose**

Create a `docker-compose.dev.yml`. Additionally, we will mount our code in a [volume](https://www.cloudsavvyit.com/7500/what-are-docker-volumes-and-how-do-you-use-them/) so that our code changes are in sync with the container during development.

```
version: "3.8"

services:
  app:
    container_name: app-dev-c
    image: app-dev-i
    build:
      context: .
      dockerfile: Dockerfile.dev
    volumes:
      - ./src:/app/src
    ports:
      - "3000:3000"

```

Let's start our React app for development!

```
docker-compose -f docker-compose.dev.yml up

```

To make life easier add docker-compose commands to `package.json`

```
"docker-dev-up": "docker-compose -f docker-compose.dev.yml up"
"docker-dev-down": "docker-compose -f docker-compose.dev.yml down"

```

Let's check our container!

```
> docker ps

REPOSITORY TAG IMAGE ID CREATED SIZE
app-dev latest 5867f4e40c98 About a minute ago 436MB

```

Visit the app at [`http://localhost:3000`](http://localhost:3000)

* * *

## Step 4: Dockerize Production env

Let's use [nginx](https://www.nginx.com/) to serve our static assets and help resolve routes when we're using [React Router](https://reactrouter.com/) or any kind of routing.

**Configure nginx**

Create a `nginx.conf` with the below content. This will help handle URI changes during routing.

```
server {
  listen 80;

  location / {
    root /usr/share/nginx/html/;
    include /etc/nginx/mime.types;
    try_files $uri $uri/ /index.html;
  }
}

```

**Init Dockerfile**

Start by adding a `Dockerfile.prod`

```
FROM node:14-alpine AS builder
ENV NODE_ENV production

# Add a work directory
WORKDIR /app

# Cache and Install dependencies
COPY package.json .
COPY yarn.lock .
RUN npm i

# Copy app files
COPY . .

# Build the app
RUN npm run build

# Bundle static assets with nginx
FROM nginx:1.21.0-alpine as production
ENV NODE_ENV production

# Copy built assets from builder
COPY --from=builder /app/build /usr/share/nginx/html

# Add your nginx.conf
COPY nginx.conf /etc/nginx/conf.d/default.conf

# Expose port
EXPOSE 80

# Start nginx
CMD ["nginx", "-g", "daemon off;"]

```

**Init docker-compose**

Add a `docker-compose.prod.yml` file

```
version: "3.8"

services:
  app:
    container_name: app-prod-c
    image: app-prod-i
    build:
      context: .
      dockerfile: Dockerfile.prod
    ports:
        - "8080:80"

```

Build production image

```
docker-compose -f docker-compose.prod.yml build

```

Let's check out our built production image

```
> docker images

REPOSITORY TAG IMAGE ID CREATED SIZE
app-prod latest c5db8d308bb9 About a minute ago 23.1MB

```

Start our production container on port `80` with the name `react-app`

```
docker run -p 8080:80 --name react-app app-prod

```

Visit the app at [`http://localhost:`](http://localhost:3000)`8080`

Here is how the final project struct looks:

```
 node_modules
 public
    index.html
   ...
    manifest.json
 src
    App.css
   ...
    index.js
 package.json
 yarn.lock
 .dockerignore
 Dockerfile.dev
 Dockerfile.prod
 docker-compose.dev.yml
 docker-compose.prod.yml

```

Hurrayyy!! We can now use docker in our workflow and deploy our production images faster to any platform.