How to Create a Dockerfile for React Applications
To create a
Dockerfile for a React app, use a multi-stage build starting with a Node image to build the app, then copy the build output to a lightweight web server image like Nginx. This approach keeps the final image small and ready to serve your React app efficiently.Syntax
A typical React Dockerfile uses multi-stage builds with these parts:
- FROM node: Use Node.js image to install dependencies and build the app.
- WORKDIR: Set the working directory inside the container.
- COPY package.json and yarn.lock/npm files: Copy dependency files first for caching.
- RUN npm install or yarn install: Install dependencies.
- COPY source code: Copy the React app source files.
- RUN npm run build: Build the React app into static files.
- FROM nginx: Use Nginx image to serve the built static files.
- COPY build output: Copy the build folder to Nginx's serving directory.
- EXPOSE 80: Open port 80 for HTTP traffic.
- CMD: Start Nginx server.
dockerfile
FROM node:18-alpine AS build WORKDIR /app COPY package.json package-lock.json ./ RUN npm install COPY . . RUN npm run build FROM nginx:stable-alpine COPY --from=build /app/build /usr/share/nginx/html EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]
Example
This example Dockerfile builds a React app and serves it with Nginx. It first installs dependencies and builds the app in a Node environment, then copies the build output to an Nginx container for efficient serving.
dockerfile
FROM node:18-alpine AS build WORKDIR /app COPY package.json package-lock.json ./ RUN npm install COPY . . RUN npm run build FROM nginx:stable-alpine COPY --from=build /app/build /usr/share/nginx/html EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]
Output
When you build and run this Dockerfile, your React app will be available on port 80, served by Nginx with optimized static files.
Common Pitfalls
Common mistakes when creating a Dockerfile for React include:
- Not using multi-stage builds, which leads to large images with unnecessary build tools.
- Copying the entire project before installing dependencies, which breaks Docker cache and slows builds.
- Forgetting to expose the correct port (usually 80 for Nginx).
- Not running the build script, so the app is not compiled into static files.
- Using a Node image to serve the app instead of a lightweight web server like Nginx.
dockerfile
### Wrong approach (no multi-stage, large image): FROM node:18-alpine WORKDIR /app COPY . . RUN npm install RUN npm run build EXPOSE 3000 CMD ["npm", "start"] ### Right approach (multi-stage, small image): FROM node:18-alpine AS build WORKDIR /app COPY package.json package-lock.json ./ RUN npm install COPY . . RUN npm run build FROM nginx:stable-alpine COPY --from=build /app/build /usr/share/nginx/html EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]
Quick Reference
Tips for creating React Dockerfiles:
- Use
node:18-alpinefor building to keep image size small. - Use multi-stage builds to separate build and runtime environments.
- Serve static files with
nginx:stable-alpinefor better performance. - Copy only necessary files before installing dependencies to leverage Docker cache.
- Expose port 80 for Nginx to serve the app.
Key Takeaways
Use multi-stage Dockerfile to build React app with Node and serve with Nginx for small, efficient images.
Copy dependency files first and run install before copying source code to optimize Docker cache.
Always run the React build script to generate static files before serving.
Expose port 80 in the final image to serve the app via Nginx.
Avoid serving React apps directly with Node in production; use a lightweight web server instead.