# 执行计划：容器化部署 Volume 挂载优化

> **文档状态**: 初稿待评审  
> **编写日期**: 2026-07-27  
> **当前分支**: `platform-auto-test`  
> **目标服务器**: 192.168.5.60 / Ubuntu 26.04 LTS / 用户 ubains  
> **关联 PRD**: `_PRD_需求文档_容器化部署Volume挂载优化.md` v1.0  
> **预计工时**: 1 天  

---

## 一、执行概述

### 1.1 任务背景

当前容器化部署在 `~/ubains-module-test/` git 目录下，代码通过 `COPY` 打包进镜像，每次更新代码需重建镜像（3-5分钟）。同时该 git 目录与另一个维护平台（8088 端口）共用，存在冲突风险。

### 1.2 执行目标

| 目标 | 描述 | 验收标准 |
|------|------|---------|
| 独立目录部署 | 将服务迁移到 `/opt/plat-auto-test/` | 服务在新目录正常运行 |
| Volume 挂载代码 | 后端代码通过 volume 挂载，改代码无需重建 | 修改代码后重启生效 |
| 前端产物挂载 | 前端构建产物通过 volume 挂载 | 上传新 dist/ 后重启生效 |
| 数据库迁移 | 将本地有数据的库迁移到服务器 | 访问平台看到 241 个 UI 用例 |
| 服务隔离 | 与另一维护平台完全独立 | 8088 端口服务不受影响 |

### 1.3 预计工期

| 阶段 | 内容 | 预计时间 |
|------|------|---------|
| Phase 1 | 本地部署配置改造 | 0.5 天 |
| Phase 2 | 服务器迁移部署 | 0.5 天 |
| Phase 3 | 数据迁移与验证 | 0.5 天 |
| **总计** | | **1.5 天** |

---

## 二、任务分解与实施计划

### Phase 1: 本地部署配置改造（0.5 天）

#### 1.1 修改 Dockerfile.backend — 去掉代码 COPY

**目标**：镜像只装依赖，不打包代码

**文件**: `deploy/Dockerfile.backend`

**变更**：
```dockerfile
# 改造前：COPY 了整个后端代码
COPY backend/ .

# 改造后：不复制代码，启动时从 volume 挂载
# 删掉这一行 COPY backend/ .
```

**完整改造后 Dockerfile.backend**：
```dockerfile
FROM python:3.10-slim

WORKDIR /app

# 安装 Playwright 系统依赖
RUN apt-get update && apt-get install -y --no-install-recommends \
    wget gnupg curl libnss3 libnspr4 libatk1.0-0t64 \
    libatk-bridge2.0-0t64 libcups2t64 libdrm2 libdbus-1-3 \
    libxkbcommon0 libxcomposite1 libxdamage1 libxfixes3 \
    libxrandr2 libgbm1 libpango-1.0-0 libcairo2 libasound2t64 \
    && rm -rf /var/lib/apt/lists/*

# 安装 Python 依赖（使用国内镜像源）
COPY backend/requirements.txt .
RUN pip install --no-cache-dir -i https://pypi.tuna.tsinghua.edu.cn/simple \
    --trusted-host pypi.tuna.tsinghua.edu.cn --retries 5 --timeout 120 -r requirements.txt

# 安装 Playwright Chromium
RUN playwright install chromium

# 创建数据目录
RUN mkdir -p /app/data/screenshots /app/data/reports

EXPOSE 8001

# 注意：代码通过 volume 挂载，不 COPY
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8001"]
```

#### 1.2 修改 Dockerfile.frontend — 去掉 dist COPY

**目标**：镜像只含 nginx 配置，构建产物从 volume 挂载

**文件**: `deploy/Dockerfile.frontend`

**变更**：
```dockerfile
# 改造前：多阶段构建，COPY 了 dist/
FROM node:20-alpine AS build
COPY frontend/ .
RUN npm run build

FROM nginx:alpine
COPY --from=build /app/dist /usr/share/nginx/html

# 改造后：纯 nginx 镜像，只复制配置
FROM nginx:alpine

# 复制 Nginx 配置
COPY deploy/nginx/default.conf /etc/nginx/conf.d/default.conf

# 不复制 dist/ —— 启动时从 volume 挂载
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
```

#### 1.3 修改 docker-compose.yml — 添加 volume 挂载

**文件**: `deploy/docker-compose.yml`

**变更**：
```yaml
services:
  backend:
    # ... 保持不变 ...
    volumes:
      - /opt/plat-auto-test/data:/app/data
      - /opt/plat-auto-test/backend:/app       # 新增：挂载后端代码
    # ... 保持不变 ...

  frontend:
    # ... 保持不变 ...
    volumes:
      - /opt/plat-auto-test/frontend/dist:/usr/share/nginx/html  # 新增：挂载前端构建产物
    # ... 保持不变 ...
```

#### 1.4 修改 deploy.sh — 适配新目录

**文件**: `deploy/deploy.sh`

**变更**：将默认路径从 `~/ubains-module-test` 改为 `/opt/plat-auto-test`

---

### Phase 2: 服务器迁移部署（0.5 天）

#### 2.1 停掉当前容器

```bash
ssh ubains@192.168.5.60
cd ~/ubains-module-test/deploy
docker compose down
```

#### 2.2 创建独立目录

```bash
sudo mkdir -p /opt/plat-auto-test/deploy/nginx
sudo mkdir -p /opt/plat-auto-test/backend
sudo mkdir -p /opt/plat-auto-test/frontend/dist
sudo mkdir -p /opt/plat-auto-test/data/screenshots
sudo mkdir -p /opt/plat-auto-test/data/reports
sudo chown -R ubains:ubains /opt/plat-auto-test
```

#### 2.3 上传部署配置

从本地上传以下文件到 `/opt/plat-auto-test/deploy/`：

| 文件 | 本地路径 | 服务器路径 |
|------|---------|-----------|
| docker-compose.yml | `deploy/docker-compose.yml` | `/opt/plat-auto-test/deploy/` |
| Dockerfile.backend | `deploy/Dockerfile.backend` | `/opt/plat-auto-test/deploy/` |
| Dockerfile.frontend | `deploy/Dockerfile.frontend` | `/opt/plat-auto-test/deploy/` |
| nginx/default.conf | `deploy/nginx/default.conf` | `/opt/plat-auto-test/deploy/nginx/` |

#### 2.4 上传后端代码

```bash
# 本地打包
cd E:\github\ubains-module-test\platform-auto-test
# 上传 backend/ 目录（排除 pycache）
scp -r backend/ ubains@192.168.5.60:/opt/plat-auto-test/backend/
```

#### 2.5 构建前端并上传

```bash
# 本地构建前端
cd frontend
npm run build

# 上传构建产物
scp -r dist/* ubains@192.168.5.60:/opt/plat-auto-test/frontend/dist/
```

#### 2.6 构建镜像并启动

```bash
cd /opt/plat-auto-test/deploy

# 首次需要构建镜像（只这一次）
docker compose build

# 启动服务
docker compose up -d

# 检查健康状态
docker compose ps
curl http://localhost:8001/health
curl http://localhost/
```

---

### Phase 3: 数据迁移与验证（0.5 天）

#### 3.1 上传有数据的数据库

```bash
# 本地：上传有数据的数据库到服务器
scp E:\github\ubains-module-test\platform-auto-test\backend\data\test_platform.db \
    ubains@192.168.5.60:/opt/plat-auto-test/data/test_platform.db
```

#### 3.2 重启后端

```bash
ssh ubains@192.168.5.60
cd /opt/plat-auto-test/deploy
docker compose restart backend
```

#### 3.3 验证数据

```bash
# 检查 API 返回用例数
curl -s "http://localhost:8001/api/cases?limit=10" | python3 -m json.tool | head -20

# 检查模块
curl -s "http://localhost:8001/api/modules?case_type=ui" | python3 -c "
import sys,json
d=json.load(sys.stdin)
print(f'UI模块数: {len(d)}')
"
```

#### 3.4 验证前端可访问

```bash
curl -s -o /dev/null -w "%{http_code}" http://localhost/
# 期望输出: 200
```

#### 3.5 验证已有服务不受影响

```bash
curl -s -o /dev/null -w "%{http_code}" http://localhost:8088/
# 期望输出: 200
```

---

## 三、更新操作指南（后续日常用）

### 改后端代码后

```bash
# 本地改完代码后，上传到服务器
scp -r backend/ ubains@192.168.5.60:/opt/plat-auto-test/backend/

# SSH 到服务器，重启容器
ssh ubains@192.168.5.60
cd /opt/plat-auto-test/deploy
docker compose restart backend
```

### 改前端代码后

```bash
# 本地改完代码后，构建并上传
cd frontend
npm run build
scp -r dist/* ubains@192.168.5.60:/opt/plat-auto-test/frontend/dist/

# SSH 到服务器，重启容器
ssh ubains@192.168.5.60
cd /opt/plat-auto-test/deploy
docker compose restart frontend
```

### 更新数据库

```bash
# 上传新的数据库文件
scp backend/data/test_platform.db ubains@192.168.5.60:/opt/plat-auto-test/data/

# 重启后端
ssh ubains@192.168.5.60
cd /opt/plat-auto-test/deploy
docker compose restart backend
```

---

## 四、验收标准

### 4.1 功能验收

| 验收项 | 操作 | 期望结果 |
|--------|------|---------|
| 独立目录运行 | 检查容器挂载 | `/opt/plat-auto-test/` 下所有文件完整 |
| 后端 volume 挂载 | 修改一个 Python 文件后重启 | 新代码生效 |
| 前端 volume 挂载 | 更新 dist/ 后重启 | 新前端生效 |
| 数据库数据完整 | 访问 API 查用例数 | 返回 241 个 UI 用例 |
| 服务隔离 | 访问 8088 端口 | 另一维护平台正常运行 |

### 4.2 性能验收

| 验收项 | 标准 |
|--------|------|
| 后端重启时间 | < 10 秒 |
| 健康检查 | HTTP 200 |
| 前端首页 | HTTP 200 |

---

## 五、风险评估

| 风险 | 概率 | 影响 | 缓解措施 |
|------|------|------|---------|
| 容器内路径 `/app` 与挂载冲突 | 中 | 高 | 确保 WORKDIR 和 volume 路径一致 |
| 旧容器未完全停止 | 低 | 中 | 先 `docker compose down` 再启动 |
| 数据库文件权限不足 | 中 | 高 | 设置 `chmod 644` 并用 `chown` 给容器用户 |
| 前端构建产物路径不对 | 低 | 中 | 确认 nginx root 指向 `/usr/share/nginx/html` |
| 忘记上传 backend/ 代码 | 低 | 高 | 启动时检查 `uvicorn` 能否找到 app.main |

---

## 六、实施记录

| 日期 | 操作 | 负责人 | 备注 |
|------|------|--------|------|
| 2026-07-27 | 编写需求文档和计划执行文档 | czj | 待实施 |

---

## 七、后续工作

| 优先级 | 待办 | 说明 |
|--------|------|------|
| P1 | 实施迁移部署 | 按 Phase 2 步骤执行 |
| P2 | 数据库迁移 | 上传有数据的 .db 文件 |
| P3 | 全量执行验证 | 迁移后执行 241 个用例验证 |
| P4 | 编写自动化更新脚本 | 简化后续更新操作 |

---

## 八、附录

### 8.1 相关文件

| 文件 | 路径 |
|------|------|
| 需求文档 | `Docs/PRD/需求文档/部署运维/_PRD_需求文档_容器化部署Volume挂载优化.md` |
| 部署方案 | `Docs/部署方案/Linux服务器部署方案.md` |
| 原始部署执行计划 | `Docs/部署方案/Linux容器化部署_执行计划.md` |
| 后端 Dockerfile | `deploy/Dockerfile.backend` |
| 前端 Dockerfile | `deploy/Dockerfile.frontend` |
| Docker Compose | `deploy/docker-compose.yml` |
| Nginx 配置 | `deploy/nginx/default.conf` |
| 部署脚本 | `deploy/deploy.sh` |

### 8.2 服务器信息

| 项目 | 值 |
|------|-----|
| 服务器 IP | 192.168.5.60 |
| SSH 用户 | ubains |
| 操作系统 | Ubuntu 26.04 LTS |
| 已有服务 | 8088 端口（`/opt/troubleshoot/`） |
| 新部署目录 | `/opt/plat-auto-test/` |
| 前端地址 | http://192.168.5.60 |
| API 文档 | http://192.168.5.60:8001/docs |