How to Serve a React App with nginx in Docker
Nick Scialli
September 06, 2020
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!
Nick Scialli is a senior UI engineer at Microsoft.