When deploying a React application using Docker, one of the main goals is to create a lightweight, optimized production image. Deploying a React app can feel trickier than deploying a backend for several reasons, even though it’s ultimately just static files. Let me break it down:
- Build Step is Required
Unlike backend apps, you can’t just runnpm startin production. You need to runnpm run buildto generate optimized static files. This adds a step to your deployment pipeline. Backend apps often just run the server with the necessary environment variables, without a separate “build” step. - Serving the App
- React apps need a static file server, like Nginx, Apache, or even Node’s
serve. Misconfiguring the server (wrong root, caching issues, or routing rules) can break the app. - Backends usually already include the server logic, so deployment is more “plug-and-play.”
Docker’s multi-stage builds make this easy by separating the build environment from the runtime environment. This ensures that your final image contains only what’s needed to serve your app, keeping it small and secure.

What are Multi-stage Docker builds?
Multi-stage builds are a Docker feature that lets you use multiple FROM statements in a single Dockerfile, each representing a separate stage. They are primarily used to separate the build environment from the runtime environment, producing smaller, cleaner, and more secure images.
Basically, you can use the image created in the first stage as an input to the second stage. This ensures that you can have separate build time instructions and runtime instructions. You copy only the final artifacts (like compiled binaries or React build folder) to a lighter, minimal image for production.
Example Multi-stage build Dockerfile for a React App
# Stage 1: Build stage
FROM node:20-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
# Stage 2: Production stage
FROM nginx:alpine
#here we use the build created in the first stage
COPY --from=build /app/build /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
Explanation:
- Stage 1 (
build): Uses Node to install dependencies and build the React app. - Stage 2 (final): Uses Nginx to serve only the optimized
buildfolder. Node and all build dependencies are not included, keeping the image small.
Benefits of Multi-stage docker builds
- Smaller image sizes → faster deployment & download
- Better security → fewer unnecessary tools in production
- Clean separation → build vs runtime environment
- Reusable stages → same build stage can be used in multiple final images
Conclusion
In short, multi-stage builds are a clean way to produce optimized Docker images by separating the “build” environment from the “production” environment. If you’re curious to explore more, check out the official Docker documentation for in-depth guides and reference material.
Want to know more about me? Check out feyashah.com or just drop a friendly hello on LinkedIn!