TypeOfNaN

How to Serve a React App with nginx in Docker

Nick Scialli
September 06, 2020

docker react nginx

Let’s create a static site in React and learn how to serve it in a Docker container using nginx. For simplicity, we’re going to just use the standard React app that is created when you use create-react-app. I’ll be using yarn, but feel free to use npm.

We will name this app react-nginx.

yarn create react-app react-nginx

Navigate to the new app folder:

cd react-nginx

Now we know we’ll need a couple files to use with Docker: a Dockerfile and a .dockerignore file. Let’s make them now.

touch Dockerfile

And for our .dockerignore file, let’s just throw node_modules in there and be done with it.

echo "node_modules" > .dockerignore

Building Out the Dockerfile

Time to build out the Dockerfile! There are a lot of ways we could do this, but today we’ll use a multi-stage process:

  • Stage 1: Node image for building frontend assets
  • Stage 2: nginx stage to serve frontend assets

Stage 1: Building the front-end assets

Our first stage will:

  • Use a node image
  • Copy all our React files into a working directory
  • Install the project dependencies with yarn
  • Build the app with yarn

Here’s how this looks in Docker!

# Name the node stage "builder"
FROM node:10 AS builder
# Set working directory
WORKDIR /app
# Copy all files from current directory to working dir in image
COPY . .
# install node modules and build assets
RUN yarn install && yarn build

Next up, we actually serve the content we just built!

Stage 2: Our nginx server

Our second stage will:

  • Use an nginx image
  • Remove any default static assets from the nginx image
  • Copy our static assets from the builder image we created in the first stage
  • Specify the entrypoint for our container to run nginx

Here’s what this stage looks like in the Dockerfile:

# nginx state for serving content
FROM nginx:alpine
# Set working directory to nginx asset directory
WORKDIR /usr/share/nginx/html
# Remove default nginx static assets
RUN rm -rf ./*
# Copy static assets from builder stage
COPY --from=builder /app/build .
# Containers run nginx with global directives and daemon off
ENTRYPOINT ["nginx", "-g", "daemon off;"]

Awesome! Let’s put it all together and actually run our app.

Putting it All Together

Our multi-stage Dockerfile should now look like this:

# Multi-stage
# 1) Node image for building frontend assets
# 2) nginx stage to serve frontend assets

# Name the node stage "builder"
FROM node:10 AS builder
# Set working directory
WORKDIR /app
# Copy all files from current directory to working dir in image
COPY . .
# install node modules and build assets
RUN yarn install && yarn build

# nginx state for serving content
FROM nginx:alpine
# Set working directory to nginx asset directory
WORKDIR /usr/share/nginx/html
# Remove default nginx static assets
RUN rm -rf ./*
# Copy static assets from builder stage
COPY --from=builder /app/build .
# Containers run nginx with global directives and daemon off
ENTRYPOINT ["nginx", "-g", "daemon off;"]

Now that we have assembled our Dockerfile, let’s build an image called react-nginx:

docker build -t react-nginx .

Now that our image is built, we can start a container with the following command, which will serve our app on port 8080.

docker run --rm -it -p 8080:80 react-nginx

Navigate to http://localhost:8080, and you should now see our default app!

If you'd like to support this blog by buying me a coffee I'd really appreciate it!

Nick Scialli

Nick Scialli is a senior UI engineer at Microsoft.

© 2024 Nick Scialli