Home Explore Blog CI



docker

2nd chunk of `content/guides/reactjs/containerize.md`
08ce152fd475d073113e1a79775ba0fdabedc75fed6040410000000100000fd3
| What version of Node do you want to use?                   | 22.14.0-alpine  |
| Which package manager do you want to use?                  | npm             |
| Do you want to run "npm run build" before starting server? | yes             |
| What directory is your build output to?                    | dist            |
| What command do you want to use to start the app?          | npm run dev     |
| What port does your server listen on?                      | 8080            |

After completion, your project directory will contain the following new files:

```text
├── docker-reactjs-sample/
│ ├── Dockerfile
│ ├── .dockerignore
│ ├── compose.yaml
│ └── README.Docker.md
```

---

## Build the Docker image

The default Dockerfile generated by `docker init` serves as a solid starting point for general Node.js applications. However, React.js is a front-end library that compiles into static assets, so we need to tailor the Dockerfile to optimize for how React applications are built and served in a production environment.

### Step 1: Review the generated files

In this step, you’ll improve the Dockerfile and configuration files by following best practices:

- Use multi-stage builds to keep the final image clean and small  
- Serve the app using NGINX, a fast and secure web server  
- Improve performance and security by only including what’s needed  

These updates help ensure your app is easy to deploy, fast to load, and production-ready.

> [!NOTE]
> A `Dockerfile` is a plain text file that contains step-by-step instructions to build a Docker image. It automates packaging your application along with its dependencies and runtime environment.  
> For full details, see the [Dockerfile reference](/reference/dockerfile/).


### Step 2: Configure the Dockerfile file 

Copy and replace the contents of your existing `Dockerfile` with the configuration below:

```dockerfile
# =========================================
# Stage 1: Build the React.js Application
# =========================================
ARG NODE_VERSION=22.14.0-alpine
ARG NGINX_VERSION=alpine3.21

# Use a lightweight Node.js image for building (customizable via ARG)
FROM node:${NODE_VERSION} AS builder

# Set the working directory inside the container
WORKDIR /app

# Copy package-related files first to leverage Docker's caching mechanism
COPY package.json package-lock.json ./

# Install project dependencies using npm ci (ensures a clean, reproducible install)
RUN --mount=type=cache,target=/root/.npm npm ci

# Copy the rest of the application source code into the container
COPY . .

# Build the React.js application (outputs to /app/dist)
RUN npm run build

# =========================================
# Stage 2: Prepare Nginx to Serve Static Files
# =========================================

FROM nginxinc/nginx-unprivileged:${NGINX_VERSION} AS runner

# Use a built-in non-root user for security best practices
USER nginx

# Copy custom Nginx config
COPY nginx.conf /etc/nginx/nginx.conf

# Copy the static build output from the build stage to Nginx's default HTML serving directory
COPY --chown=nginx:nginx  --from=builder /app/dist /usr/share/nginx/html

# Expose port 8080 to allow HTTP traffic
# Note: The default NGINX container now listens on port 8080 instead of 80 
EXPOSE 8080

# Start Nginx directly with custom config
ENTRYPOINT ["nginx", "-c", "/etc/nginx/nginx.conf"]
CMD ["-g", "daemon off;"]
```

### Step 3: Configure the .dockerignore file

The `.dockerignore` file tells Docker which files and folders to exclude when building the image.


> [!NOTE]
>This helps:
>- Reduce image size  
>- Speed up the build process  
>- Prevent sensitive or unnecessary files (like `.env`, `.git`, or `node_modules`) from being added to the final image.
>
> To learn more, visit the [.dockerignore reference](/reference/dockerfile.md#dockerignore-file).

Copy and replace the contents of your existing `.dockerignore` with the configuration below:

```dockerignore
# Ignore dependencies and build output

Title: Improving the Dockerfile and Configuration Files
Summary
The generated Dockerfile from docker init needs to be improved to fully optimize a React application, including using multi-stage builds, serving via NGINX, and improving performance/security. The updated Dockerfile uses a multi-stage build, first using a Node.js image to build the React application and then using an NGINX image to serve the static files. The `.dockerignore` file is configured to exclude unnecessary files like dependencies and build output from the Docker image to reduce its size.