Docker 容器化部署前端项目实战
概述
本文讲解前端项目的两种容器化部署方式:Volume 映射(快速测试)和构建镜像(生产推荐),涵盖 Docker Compose 配置、端口映射、Volume 映射、Nginx 配置及多阶段构建 Dockerfile。
前置知识
- Nest 项目如何编写 Dockerfile
- 提升 Dockerfile 水平的 5 个技巧
- Nginx 基础配置与 Linux 基本操作
学习目标
- 理解两种前端容器化方式的优劣与适用场景
- 掌握 Docker Compose 端口映射与 Volume 映射配置
- 熟练编写前端多阶段构建 Dockerfile
- 能够完成从构建到部署的完整流程
一、两种容器化方式对比
| 维度 | Volume 映射 | 构建镜像(推荐) |
|---|---|---|
| 原理 | Nginx 官方镜像 + 宿主机目录映射 | 编写 Dockerfile,代码打包进镜像 |
| 环境独立性 | 依赖宿主机目录 | 完全独立 |
| 部署速度 | 快(无需构建) | 首次慢,后续秒级 |
| 版本管理 | 无 | 镜像版本控制 |
| CI/CD 友好 | 差 | 好 |
| 适用场景 | 快速测试、开发环境 | 生产环境、多环境部署 |
二、方式一:Docker + Nginx + Volume 映射
Docker Compose 配置
yaml
version: '3'
services:
nginx:
restart: always
image: nginx
container_name: frontend-nginx
environment:
- TZ=Asia/Shanghai
ports:
- "4080:80" # 宿主机端口:容器端口
volumes:
- /home/website:/usr/share/nginx/html # 网站目录
- /etc/nginx/conf.d:/etc/nginx/conf.d # Nginx 配置
- /var/log/nginx:/var/log/nginx # 日志目录端口映射原理
code
浏览器 → http://server-ip:4080
→ Docker 映射到容器 80 端口
→ Nginx 监听 80 端口,响应请求关键规则:
- 宿主机端口不能冲突
- 容器端口必须与 Nginx
listen配置一致 - 修改 Nginx 配置后需重启容器:
docker restart frontend-nginx
Nginx 配置示例
nginx
# /etc/nginx/conf.d/site.conf
server {
listen 80;
server_name example.com;
location / {
root /usr/share/nginx/html/my-app;
index index.html;
try_files $uri $uri/ /index.html; # SPA 路由支持
}
}部署流程
bash
# 1. 构建前端项目
npm run build
# 2. 上传产物到服务器
rsync -avz dist/ user@server:/home/website/my-app/
# 3. 启动容器
docker compose up -d
# 4. 更新部署(无需重建容器)
rsync -avz dist/ user@server:/home/website/my-app/
docker exec frontend-nginx nginx -s reload三、方式二:构建 Docker 镜像(推荐)
.dockerignore
plaintext
node_modules
dist
.git
.github
.DS_Store
*.log
.env*多阶段构建 Dockerfile(Vue/React SPA)
dockerfile
# 构建阶段
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# 生产阶段
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]多阶段构建 Dockerfile(Nuxt3 SSR)
dockerfile
# 构建阶段
FROM node:18-alpine AS builder
WORKDIR /app
RUN npm config set registry https://registry.npmmirror.com
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
# 生产阶段
FROM node:18-alpine AS production
WORKDIR /app
COPY --from=builder /app/.output ./.output
EXPOSE 3000
ENV NODE_ENV=production
CMD ["node", ".output/server/index.mjs"]Nuxt3 的 .output 目录通过 bundleDependencies 自动打包所有运行时依赖,生产阶段无需 npm install。
四、镜像构建与运行
bash
# 构建镜像
docker build -t my-frontend:1.0 .
# 运行容器
docker run -d --name frontend -p 8080:80 my-frontend:1.0
# 查看日志
docker logs -f frontend
# 停止/删除
docker stop frontend && docker rm frontend
# 强制重新构建(清除缓存)
docker build --no-cache -t my-frontend:1.0 .五、环境变量配置
命令行传递
bash
docker run -d -p 3000:3000 \
-e BASE_URL=http://api.example.com \
-e API_KEY=xxx \
my-nuxt-app:1.0Docker Compose + .env 文件(推荐)
yaml
version: '3.8'
services:
nuxt-app:
image: nuxt-app:1.0
container_name: nuxt-app-prod
restart: always
ports:
- "3000:3000"
env_file:
- .env.productionbash
# .env.production
BASE_URL=http://api.example.com
API_KEY=your_api_key
NODE_ENV=production常见问题
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 端口被占用 | 宿主机端口冲突 | 修改 ports 映射或停止占用进程 |
| 页面 404 | SPA 路由未配置 try_files | Nginx 添加 try_files $uri /index.html |
| 容器启动即退出 | 启动命令错误 | docker logs 查看错误日志 |
| 构建缓存导致旧代码 | Docker 层缓存 | docker build --no-cache |
| node_modules 兼容问题 | 跨平台 native 模块 | .dockerignore 排除,容器内重新安装 |
问题排查流程
bash
docker ps -a # 查看容器状态
docker logs -f <container> # 查看日志
docker exec -it <container> sh # 进入容器调试
netstat -tlnp | grep <port> # 检查端口占用
docker build --no-cache -t app:1.0 . # 重新构建最佳实践
- 生产环境优先使用构建镜像方式,确保环境一致性
- 使用
.dockerignore排除 node_modules,容器内安装避免跨平台问题 - 容器构建使用 npm(而非 pnpm),避免软链接在容器内的路径问题
- 镜像标签使用语义化版本号,便于回滚
- 敏感配置通过
.env文件或 Docker Secret 注入,不写入镜像