容器化一个 React.js 应用程序
先决条件
开始之前,请确保您的系统上已安装并可使用以下工具:
- 您已安装最新版本的 Docker Desktop。
- 您有一个 git 客户端。本节中的示例使用基于命令行的 git 客户端,但您可以使用任何客户端。
Docker 新手?
从 Docker 基础知识 指南开始,熟悉镜像、容器和 Dockerfile 等关键概念。
概述
本指南将引导您完成使用 Docker 容器化 React.js 应用程序的完整过程。您将学习如何使用最佳实践创建生产就绪的 Docker 镜像,这些实践可提高性能、安全性、可伸缩性和部署效率。
完成本指南后,您将:
- 使用 Docker 容器化 React.js 应用程序。
- 为生产构建创建和优化 Dockerfile。
- 使用多阶段构建最小化镜像大小。
- 使用自定义 NGINX 配置高效地提供应用程序。
- 遵循最佳实践来构建安全且可维护的 Docker 镜像。
获取示例应用程序
克隆示例应用程序以与本指南一起使用。打开终端,将目录更改为您想要工作的目录,然后运行以下命令克隆 git 仓库:
$ git clone https://github.com/kristiyan-velkov/docker-reactjs-sample
生成 Dockerfile
Docker 提供了一个名为 docker init 的交互式 CLI 工具,可帮助搭建容器化应用程序所需的配置文件。这包括生成 Dockerfile、.dockerignore、compose.yaml 和 README.Docker.md。
首先,导航到项目根目录:
$ cd docker-reactjs-sample
然后运行以下命令:
$ docker init
您将看到类似于以下内容的输出:
Welcome to the Docker Init CLI!
This utility will walk you through creating the following files with sensible defaults for your project:
- .dockerignore
- Dockerfile
- compose.yaml
- README.Docker.md
Let's get started!CLI 将提示您一些关于应用程序设置的问题。为了一致性,请在提示时使用与以下示例中所示相同的回答:
| 问题 | 回答 |
|---|---|
| 您的项目使用什么应用程序平台? | 节点 |
| 您想使用哪个版本的 Node? | 22.14.0-alpine |
| 您想使用哪个包管理器? | npm |
| 您想在启动服务器之前运行 "npm run build" 吗? | 是 |
| 您的构建输出到哪个目录? | dist |
| 您想使用什么命令来启动应用程序? | npm run dev |
| 您的服务器监听哪个端口? | 8080 |
完成后,您的项目目录将包含以下新文件:
├── docker-reactjs-sample/
│ ├── Dockerfile
│ ├── .dockerignore
│ ├── compose.yaml
│ └── README.Docker.md构建 Docker 镜像
docker init 生成的默认 Dockerfile 是通用 Node.js 应用程序的良好起点。然而,React.js 是一个编译成静态资产的前端库,因此我们需要根据 React 应用程序在生产环境中的构建和提供方式来优化 Dockerfile。
步骤 1:审查生成的文件
在此步骤中,您将通过遵循最佳实践来改进 Dockerfile 和配置文件:
- 使用多阶段构建以保持最终镜像的干净和精简
- 使用 NGINX(一个快速且安全的 Web 服务器)提供应用程序
- 仅包含所需内容以提高性能和安全性
这些更新有助于确保您的应用程序易于部署、快速加载并为生产做好准备。
注意
Dockerfile是一个纯文本文件,其中包含构建 Docker 镜像的分步说明。它自动化了应用程序及其依赖项和运行时环境的打包。
有关完整详细信息,请参阅 Dockerfile 参考。
步骤 2:配置 Dockerfile 文件
复制以下配置并替换您现有的 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;"]步骤 3:配置 .dockerignore 文件
.dockerignore 文件告诉 Docker 在构建镜像时要排除哪些文件和文件夹。
注意
复制并用以下配置替换您现有的 .dockerignore 的内容:
# Ignore dependencies and build output
node_modules/
dist/
out/
.tmp/
.cache/
# Ignore Vite, Webpack, and React-specific build artifacts
.vite/
.vitepress/
.eslintcache
.npm/
coverage/
jest/
cypress/
cypress/screenshots/
cypress/videos/
reports/
# Ignore environment and config files (sensitive data)
*.env*
*.log
# Ignore TypeScript build artifacts (if using TypeScript)
*.tsbuildinfo
# Ignore lockfiles (optional if using Docker for package installation)
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# Ignore local development files
.git/
.gitignore
.vscode/
.idea/
*.swp
.DS_Store
Thumbs.db
# Ignore Docker-related files (to avoid copying unnecessary configs)
Dockerfile
.dockerignore
docker-compose.yml
docker-compose.override.yml
# Ignore build-specific cache files
*.lock步骤 4:创建 nginx.conf 文件
为了在容器内高效地提供您的 React.js 应用程序,您将使用自定义设置配置 NGINX。此配置针对性能、浏览器缓存、gzip 压缩和客户端路由支持进行了优化。
在项目根目录中创建一个名为 nginx.conf 的文件,并添加以下内容:
注意要了解有关配置 NGINX 的更多信息,请参阅 官方 NGINX 文档。
worker_processes auto;
# Store PID in /tmp (always writable)
pid /tmp/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Disable logging to avoid permission issues
access_log off;
error_log /dev/stderr warn;
# Optimize static file serving
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
keepalive_requests 1000;
# Gzip compression for optimized delivery
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml;
gzip_min_length 256;
gzip_vary on;
server {
listen 8080;
server_name localhost;
# Root directory where React.js build files are placed
root /usr/share/nginx/html;
index index.html;
# Serve React.js static files with proper caching
location / {
try_files $uri /index.html;
}
# Serve static assets with long cache expiration
location ~* \.(?:ico|css|js|gif|jpe?g|png|woff2?|eot|ttf|svg|map)$ {
expires 1y;
access_log off;
add_header Cache-Control "public, immutable";
}
# Handle React.js client-side routing
location /static/ {
expires 1y;
add_header Cache-Control "public, immutable";
}
}
}步骤 5:构建 React.js 应用程序镜像
配置好自定义设置后,您现在可以为您的 React.js 应用程序构建 Docker 镜像了。
更新后的设置包括:
- 优化的浏览器缓存和 gzip 压缩
- 安全的非 root 日志记录以避免权限问题
- 通过将不匹配的路由重定向到
index.html来支持 React 客户端路由
完成上述步骤后,你的项目目录现在应该包含以下文件
├── docker-reactjs-sample/
│ ├── Dockerfile
│ ├── .dockerignore
│ ├── compose.yaml
│ ├── nginx.conf
│ └── README.Docker.md现在您的 Dockerfile 已配置完毕,您可以为您的 React.js 应用程序构建 Docker 镜像了。
注意
docker build命令使用 Dockerfile 中的指令将您的应用程序打包成一个镜像。它包含来自当前目录(称为构建上下文)的所有必要文件。
从项目根目录运行以下命令:
$ docker build --tag docker-reactjs-sample .
此命令的作用:
- 使用当前目录中的 Dockerfile (.)
- 将应用程序及其依赖项打包到 Docker 镜像中
- 将镜像标记为 docker-reactjs-sample,以便您以后可以引用它
步骤 6:查看本地镜像
构建 Docker 镜像后,您可以使用 Docker CLI 或 Docker Desktop 检查本地计算机上可用的镜像。由于您已经在终端中工作,因此我们使用 Docker CLI。
要列出所有本地可用的 Docker 镜像,请运行以下命令:
$ docker images
示例输出
REPOSITORY TAG IMAGE ID CREATED SIZE
docker-reactjs-sample latest f39b47a97156 14 seconds ago 75.8MB此输出提供了有关镜像的关键详细信息:
- 仓库 – 分配给镜像的名称。
- 标签 – 一个版本标签,有助于识别不同的构建(例如,最新)。
- 镜像 ID – 镜像的唯一标识符。
- 创建时间 – 镜像构建时的时间戳。
- 大小 – 镜像使用的总磁盘空间。
如果构建成功,您应该会看到列出的 docker-reactjs-sample 镜像。
运行容器化应用程序
在前面的步骤中,您为 React.js 应用程序创建了一个 Dockerfile,并使用 docker build 命令构建了一个 Docker 镜像。现在是时候在容器中运行该镜像并验证您的应用程序是否按预期工作了。
在 docker-reactjs-sample 目录中,在终端中运行以下命令。
$ docker compose up --build
打开浏览器,在 https://:8080 查看应用程序。您应该会看到一个简单的 React.js Web 应用程序。
在终端中按 ctrl+c 停止您的应用程序。
在后台运行应用程序
您可以通过添加 -d 选项将应用程序与终端分离运行。在 docker-reactjs-sample 目录中,在终端中运行以下命令。
$ docker compose up --build -d
打开浏览器并在 https://:8080 查看应用程序。您应该会看到一个简单的 Web 应用程序预览。
要确认容器正在运行,请使用 docker ps 命令:
$ docker ps
这将列出所有活动的容器及其端口、名称和状态。查找暴露端口 8080 的容器。
示例输出
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
88bced6ade95 docker-reactjs-sample-server "nginx -c /etc/nginx…" About a minute ago Up About a minute 0.0.0.0:8080->8080/tcp docker-reactjs-sample-server-1要停止应用程序,请运行:
$ docker compose down
注意有关 Compose 命令的更多信息,请参阅Compose CLI 参考。
摘要
在本指南中,您学习了如何使用 Docker 容器化、构建和运行 React.js 应用程序。通过遵循最佳实践,您创建了一个安全、优化且生产就绪的设置。
你完成了什么
- 使用
docker init初始化您的项目,以搭建基本的 Docker 配置文件。 - 用一个多阶段构建替换了默认的
Dockerfile,该构建编译 React.js 应用程序并使用 Nginx 提供静态文件。 - 替换默认的
.dockerignore文件,以排除不必要的文件,保持镜像干净高效。 - 使用
docker build构建您的 Docker 镜像。 - 使用
docker compose up运行容器,包括在前台和分离模式下。 - 通过访问 https://:8080 验证应用程序是否正在运行。
- 学习了如何使用
docker compose down停止容器化应用程序。
您现在拥有一个完全容器化的 React.js 应用程序,它在 Docker 容器中运行,并可以自信而一致地部署到任何环境。
相关资源
探索官方参考资料和最佳实践以提升您的 Docker 工作流
- 多阶段构建 – 了解如何分离构建和运行时阶段。
- 编写 Dockerfile 的最佳实践 – 编写高效、可维护且安全的 Dockerfile。
- Docker 中的构建上下文 – 了解上下文如何影响镜像构建。
docker initCLI 参考 – 自动搭建 Docker 资产。docker buildCLI 参考 – 从 Dockerfile 构建 Docker 镜像。docker imagesCLI 参考 – 管理和检查本地 Docker 镜像。docker compose upCLI 参考 – 启动和运行多容器应用程序。docker compose downCLI 参考 – 停止并删除容器、网络和卷。
后续步骤
您的 React.js 应用程序现在已容器化,您可以进入下一步。
在下一节中,您将学习如何使用 Docker 容器开发您的应用程序,从而在任何机器上实现一致、隔离和可重现的开发环境。