# SmartClean 自动化部署使用手册

## 概述

本项目提供两套独立的自动化部署方案，可同时使用、互不干扰：

| 方案 | 目录 | 适用场景 | 依赖 |
|------|------|---------|------|
| **远程服务器部署** | `deploy/remote/` | 部署到 182 测试/生产服务器 | SSH 免密登录 |
| **Docker 本机模拟** | `deploy/docker/` | 本机模拟完整生产环境 | Docker Desktop |

---

## 现状分析

### 当前部署方式

| 环节 | 现状 | 问题 |
|------|------|------|
| **构建** | 本地执行 `build.sh`，手动触发 | 已自动化，含飞书通知 |
| **上传** | 手动 SCP 或 FTP 上传到 182 服务器 | 无标准化流程，依赖个人操作习惯 |
| **部署** | SSH 登录服务器，手动替换文件、重启服务 | 步骤多、易出错、无操作记录 |
| **回滚** | 无备份机制，出问题需手动找旧版本 | 无法快速回滚，故障恢复时间长 |
| **通知** | 构建结果有飞书通知，部署结果无通知 | 团队无法感知部署状态 |
| **环境一致性** | 服务器环境手动搭建维护 | 本地与服务器环境可能不一致 |

### 现有脚本

| 脚本 | 用途 | 覆盖范围 |
|------|------|---------|
| `build.sh` | 本地构建（Maven + npm），支持分模块构建，含飞书通知 | 仅构建，不含部署 |
| `start.sh` | 本地启动开发环境（mvn spring-boot:run + npm run dev） | 仅本地开发，非生产部署 |

### 现有流程 vs 新方案对比

```
现有流程（5 步手动操作，约 10-15 分钟）：
┌──────────┐   手动    ┌──────────┐   手动    ┌──────────┐   手动    ┌──────────┐
│ build.sh │ ───────→ │ SCP 上传  │ ───────→ │ SSH 替换  │ ───────→ │ 手动重启  │
│ 本地构建  │          │ 到服务器   │          │ 文件      │          │ 服务      │
└──────────┘          └──────────┘          └──────────┘          └──────────┘
  ✅ 已自动化            ❌ 手动               ❌ 手动               ❌ 手动
  ✅ 有飞书通知          ❌ 无记录             ❌ 无备份             ❌ 无健康检查

方案一 — 远程部署（1 条命令，全自动）：
┌──────────────────────────────────────────────────────────────────────┐
│  deploy/remote/deploy.sh web                                        │
│  构建 → 备份 → 上传 → 重启 → 健康检查 → 飞书通知（失败自动回滚）      │
└──────────────────────────────────────────────────────────────────────┘

方案二 — Docker 部署（1 条命令，全自动）：
┌──────────────────────────────────────────────────────────────────────┐
│  deploy/docker/deploy.sh web                                        │
│  镜像构建 → 容器替换 → 健康检查 → 飞书通知（失败自动回滚）             │
└──────────────────────────────────────────────────────────────────────┘
```

### 新方案解决的问题

| 现状痛点 | 方案一（远程部署） | 方案二（Docker） |
|----------|------------------|-----------------|
| 手动上传、易传错 | SCP 自动传输，路径固定 | 不需要传输，镜像自包含 |
| 无备份，无法回滚 | 每次部署自动备份，一键回滚 | 基于镜像 tag 回滚 |
| 部署步骤多、易遗漏 | 一条命令完成全部步骤 | 一条命令完成全部步骤 |
| 团队不知道谁部署了什么 | 飞书通知含版本/分支/操作人 | 飞书通知含版本/分支 |
| 部署后不确认是否成功 | 自动健康检查，失败自动回滚 | 自动健康检查，失败自动回滚 |
| 新人不知道怎么部署 | 看文档执行一条命令即可 | 一键启动完整环境 |

---

## 落地调整工作清单

### 方案一（远程部署）落地前需要做的事

#### 一次性准备工作

| # | 任务 | 说明 | 负责人 | 耗时预估 |
|---|------|------|--------|---------|
| 1 | **配置 SSH 免密登录** | 本机生成密钥，`ssh-copy-id` 到 182 服务器 | 开发者 | 5 分钟 |
| 2 | **确认服务器目录结构** | 登录 182 确认 Tomcat 实际安装路径、Nginx 配置路径、Task JAR 存放路径 | 开发者 | 10 分钟 |
| 3 | **修改 config.sh** | 将 `TOMCAT_HOME`、`NGINX_HTML` 等路径改为服务器实际路径 | 开发者 | 5 分钟 |
| 4 | **执行 setup 初始化** | `deploy/remote/deploy.sh setup` 创建标准目录 + 上传重启脚本 | 开发者 | 2 分钟 |
| 5 | **调整重启脚本** | 根据服务器实际情况微调 `restart-web.sh` / `restart-task.sh`（如 Tomcat 启停方式、Task 服务的 JVM 参数） | 开发者 | 15 分钟 |
| 6 | **首次全量部署测试** | 执行 `deploy/remote/deploy.sh` 验证全流程跑通 | 开发者 | 10 分钟 |

#### 需确认的服务器信息

在落地之前，请先 SSH 到 182 服务器确认以下信息，并更新到 `config.sh`：

```bash
# 登录服务器后执行以下命令，记录输出

# 1. Tomcat 安装路径
find / -name "catalina.sh" -type f 2>/dev/null
# 将结果的父目录的父目录填入 TOMCAT_HOME

# 2. Nginx 前端文件路径
nginx -T 2>/dev/null | grep "root "
# 将 root 路径填入 NGINX_HTML

# 3. Task 服务当前运行方式
ps -ef | grep "intellectual-task"
# 确认 JAR 名称、启动参数，更新 TASK_JAR_NAME 和 TASK_JVM_OPTS

# 4. 当前 WAR 包位置
find / -name "ROOT.war" -type f 2>/dev/null

# 5. Java 版本
java -version
```

### 方案二（Docker 本机模拟）落地前需要做的事

| # | 任务 | 说明 | 负责人 | 耗时预估 |
|---|------|------|--------|---------|
| 1 | **安装 Docker Desktop** | 如未安装，从官网下载安装 | 开发者 | 10 分钟 |
| 2 | **确认端口无冲突** | 确保 8180/18095/18097/3307/6380 未被占用，如有冲突在 `.env` 中调整 | 开发者 | 2 分钟 |
| 3 | **检查 SQL 初始化脚本** | 确认 `sql/` 目录下有完整的建库建表 SQL（Docker MySQL 首次启动会自动导入） | 开发者 | 5 分钟 |
| 4 | **首次全量部署测试** | 执行 `deploy/docker/deploy.sh`，首次需下载基础镜像 + 编译，耗时较长 | 开发者 | 20-30 分钟 |
| 5 | **验证前端 API 代理** | 确认 Nginx 的 `/api/` 反代规则与前端实际请求路径匹配（当前前端直接请求后端，无 `/api` 前缀，可能需要调整 `nginx.conf`） | 开发者 | 10 分钟 |

#### 可能需要的代码调整

| 调整项 | 原因 | 影响范围 |
|--------|------|---------|
| **前端 .env.docker**（可选） | Docker 环境中前端通过 Nginx 反代访问后端，API 地址可能需要调整 | 新增一个 `.env.docker` 文件 |
| **nginx.conf 反代路径** | 当前前端直接调用后端接口（无 `/api` 前缀），需确认 Nginx `location /api/` 的 rewrite 规则与前端请求路径一致 | `deploy/docker/conf/nginx.conf` |
| **application-docker.yml 补全** | 当前只覆盖了数据源和 Redis，如果后端有其他外部依赖（如 OSS、短信等），需补充配置或 mock | `deploy/docker/conf/application-docker.yml` |

---

## 方案一：远程服务器部署（无 Docker）

> 本地构建 → SCP 上传 → 远程重启 → 健康检查 → 失败自动回滚 → 飞书通知

### 前置条件

1. 本机已安装 Java 8、Maven、Node.js 16+
2. SSH 免密登录到目标服务器

```bash
# 配置 SSH 免密（一次性）
ssh-keygen -t ed25519
ssh-copy-id root@192.168.1.182

# 验证
ssh root@192.168.1.182 "echo ok"
```

### 首次使用

```bash
# 1. 根据实际环境修改配置
vi deploy/remote/config.sh

# 2. 初始化服务器目录结构 + 上传管理脚本
deploy/remote/deploy.sh setup
```

### 日常使用

```bash
# ===== 部署 =====

# 全量部署（前端 + 后端全部）
deploy/remote/deploy.sh

# 只改了后端 Web 代码
deploy/remote/deploy.sh web

# 只改了 Task 服务代码
deploy/remote/deploy.sh task

# 后端都改了
deploy/remote/deploy.sh backend

# 只改了前端（生产包）
deploy/remote/deploy.sh front

# 前端测试环境包
deploy/remote/deploy.sh front-test

# ===== 回滚 =====

# 回滚到上一版本
deploy/remote/deploy.sh rollback
# 或
deploy/remote/rollback.sh

# ===== 状态查看 =====

# 查看服务器服务状态
deploy/remote/deploy.sh status
```

### 配置说明

编辑 `deploy/remote/config.sh`：

```bash
# 服务器地址（根据实际修改）
DEPLOY_HOST="192.168.1.182"
DEPLOY_USER="root"

# Tomcat 路径（根据服务器实际路径修改）
TOMCAT_HOME="/opt/smartclean/web/tomcat"

# 备份保留数量
MAX_BACKUPS=5

# 健康检查重试次数和间隔
HEALTHCHECK_RETRIES=20
HEALTHCHECK_INTERVAL=5
```

### 部署流程

```
1. 本地构建  →  调用 build.sh 生成 ROOT.war / task.jar / dist/
2. 远程备份  →  SSH 备份服务器当前版本到 backups/时间戳-hash/
3. 上传产物  →  SCP 传输到服务器对应目录
4. 远程重启  →  SSH 执行 restart-web.sh / restart-task.sh / restart-front.sh
5. 健康检查  →  轮询接口，最多重试 20 次（每次间隔 5s）
6. 结果通知  →  成功/失败/回滚 均推送飞书群
```

### 服务器目录结构

```
/opt/smartclean/
├── web/tomcat/webapps/ROOT.war    # Web 服务
├── task/task.jar                  # Task 服务
├── front/dist/                    # 前端静态文件
├── backups/                       # 版本备份（自动保留最近 5 个）
│   ├── 20260415-153000-a1b2c3d/
│   └── 20260415-140000-d4e5f6a/
└── scripts/                       # 服务管理脚本
    ├── restart-web.sh
    ├── restart-task.sh
    └── restart-front.sh
```

---

## 方案二：Docker 本机模拟

> Docker 镜像构建 → Compose 部署 → 健康检查 → 失败自动回滚 → 飞书通知

### 前置条件

1. 已安装 Docker Desktop 并启动

```bash
# 验证
docker --version
docker compose version
```

### 首次使用

```bash
# 直接一键部署（首次会自动拉取基础镜像 + 构建 + 启动）
deploy/docker/deploy.sh
```

### 日常使用

```bash
# ===== 部署 =====

# 全量部署
deploy/docker/deploy.sh

# 只改了后端 Web 代码
deploy/docker/deploy.sh web

# 只改了 Task 服务代码
deploy/docker/deploy.sh task

# 只改了前端
deploy/docker/deploy.sh front

# ===== 回滚 =====

# 回滚到上一版本（基于镜像 tag）
deploy/docker/deploy.sh rollback
# 或
deploy/docker/rollback.sh

# ===== 运维 =====

# 查看容器状态
deploy/docker/deploy.sh status

# 查看所有服务日志
deploy/docker/deploy.sh logs

# 只看 Web 服务日志
deploy/docker/deploy.sh logs web

# 停止所有容器（数据保留）
deploy/docker/deploy.sh stop

# 停止并清理数据卷（慎用，会丢数据库数据）
deploy/docker/deploy.sh clean
```

### 端口映射

| 服务 | 容器内端口 | 宿主机端口 | 访问地址 |
|------|-----------|-----------|---------|
| 前端 (Nginx) | 80 | **8180** | http://localhost:8180 |
| Web 后端 | 8095 | **18095** | http://localhost:18095 |
| Task 后端 | 8097 | **18097** | http://localhost:18097 |
| MySQL | 3306 | **3307** | localhost:3307 |
| Redis | 6379 | **6380** | localhost:6380 |

> 端口可在 `deploy/docker/.env` 中自定义修改。

### 端口隔离说明

Docker 环境与本机开发环境完全独立：

```
本机开发环境                    Docker 模拟环境
──────────────                ──────────────
前端    localhost:8079         前端    localhost:8180
Web     localhost:8095         Web     localhost:18095
MySQL   localhost:3306         MySQL   localhost:3307
Redis   localhost:6379         Redis   localhost:6380
```

两套可以同时运行，互不干扰。

### 连接 Docker 中的数据库调试

```bash
# 用本机 MySQL 客户端连接 Docker 中的 MySQL
mysql -h127.0.0.1 -P3307 -uroot -pkaixinjiuhao

# 用本机 Redis 客户端连接 Docker 中的 Redis
redis-cli -h 127.0.0.1 -p 6380 -a kaixinjiuhao
```

---

## 两套方案对比

| 维度 | 远程服务器部署 | Docker 本机模拟 |
|------|--------------|----------------|
| **部署目标** | 192.168.1.182 远程服务器 | 本机 Docker 容器 |
| **依赖** | SSH 免密登录 | Docker Desktop |
| **构建方式** | 本机 mvn/npm 构建，上传产物 | Docker 多阶段构建（镜像内编译） |
| **部署速度** | 快（只传几十 MB 产物） | 慢（首次构建镜像，后续有缓存） |
| **环境一致性** | 依赖服务器已有环境 | 镜像自包含，完全一致 |
| **回滚方式** | 文件级（还原备份的 WAR/JAR/dist） | 镜像级（切换 Docker 镜像 tag） |
| **数据库** | 使用服务器上的 MySQL | 独立 MySQL 容器（数据隔离） |
| **适合场景** | 日常发布到测试/生产 | 本机验证部署流程、新人搭环境 |

## 命令速查表

```bash
# ==================== 远程部署 ====================
deploy/remote/deploy.sh              # 全量部署到远程服务器
deploy/remote/deploy.sh web          # 只部署 Web
deploy/remote/deploy.sh task         # 只部署 Task
deploy/remote/deploy.sh front        # 只部署前端
deploy/remote/deploy.sh backend      # 部署后端（web + task）
deploy/remote/deploy.sh rollback     # 回滚
deploy/remote/deploy.sh status       # 查看服务器状态
deploy/remote/deploy.sh setup        # 首次初始化服务器

# ==================== Docker 部署 ====================
deploy/docker/deploy.sh              # 全量部署到 Docker
deploy/docker/deploy.sh web          # 只部署 Web
deploy/docker/deploy.sh task         # 只部署 Task
deploy/docker/deploy.sh front        # 只部署前端
deploy/docker/deploy.sh rollback     # 回滚
deploy/docker/deploy.sh status       # 查看容器状态
deploy/docker/deploy.sh logs [服务]   # 查看日志
deploy/docker/deploy.sh stop         # 停止容器
deploy/docker/deploy.sh clean        # 停止并清理数据
```

## 飞书通知

两套方案都集成了飞书 Webhook 通知，部署结果会自动推送到群里：

- ✅ **部署成功**：版本号、分支、提交信息、耗时
- ❌ **部署失败**：自动回滚后通知，附失败原因
- ⚠️ **手动回滚**：回滚版本号、操作人

Webhook 地址在各自的配置文件中修改：
- 远程版：`deploy/remote/config.sh` → `FEISHU_WEBHOOK`
- Docker 版：`deploy/docker/.env` → `FEISHU_WEBHOOK`

## 注意事项

1. **deploy/docker/.env 不要提交到 git**（含密码），已在 .gitignore 中排除
2. **首次 Docker 构建较慢**（需下载基础镜像 + Maven 依赖），后续有缓存会快很多
3. **远程部署前确认 config.sh 中的路径**与服务器实际一致，特别是 `TOMCAT_HOME`
4. **回滚只保留最近 5 个版本**，超出自动清理（可在配置中调整 `MAX_BACKUPS`）
5. **Docker 版 Task 服务**可能因缺少 MQTT/XXL-Job 而启动异常，这是正常的，不影响 Web 和前端
