TypeOfNaN

How to Serve a React App with nginx in Docker

Nick Scialli September 06, 2020🚀 4 minute read

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!

Did this post help you?

I'd appreciate your feedback so I can make my blog posts more helpful. Did this post help you learn something or fix an issue you were having?

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

Nick Scialli

Nick Scialli is a software engineer at the U.S. Digital Service.