material_manage_system/DEPLOY.md

224 lines
7.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Docker 部署指南
## 项目简介
仓库物料管理系统 (WMMS) - 前后端分离架构
- **后端**: Go + Gin + MySQL (端口 8082)
- **前端**: Vue 3 + Vite + Nginx (端口 80)
- **数据库**: MySQL 8.0 (端口 3306)
## 快速启动 (Windows)
### 前置条件
1. 安装 [Docker Desktop](https://www.docker.com/products/docker-desktop/) (Windows 10/11)
2. 启动 Docker Desktop
### 启动服务
```bash
# 进入项目目录
cd c:\1111\12.project\VSCode\warehouse-mms
# 启动所有服务
docker-compose up -d
# 查看服务状态
docker-compose ps
```
### 访问应用
- 前端地址: http://localhost
- 后端API: http://localhost:8082/api (绑定在 `127.0.0.1`,仅限本机)
- 健康检查: http://localhost:8082/api/health
### 用手机 / 局域网其他设备访问
手机连上**与电脑同一个 WiFi**,浏览器打开 `http://<电脑的局域网IP>`,用下节账号登录即可,**不需要带端口号**(80 是 HTTP 的默认端口,浏览器会自动使用)。
先查看电脑的局域网 IP —— 取 `WLAN` 那一行的地址,忽略 `vEthernet (WSL)`、`VMware Network Adapter` 这些虚拟网卡:
```bash
ipconfig
```
例如地址是 `192.168.31.76`,手机就访问 `http://192.168.31.76`。
**为什么不需要改配置**:前端请求走相对路径 `/api`,手机访问时会自动打到 `http://<电脑IP>/api`,再由 Nginx 反代给后端容器。前后端都没有硬编码 `localhost`,所以换任何 IP 访问都能正常工作。
#### 端口绑定策略
| 服务 | 绑定地址 | 局域网可访问 | 原因 |
|------|----------|--------------|------|
| frontend | `0.0.0.0:80` | ✅ 是 | 手机、其他设备要打开网页 |
| backend | `127.0.0.1:8082` | ❌ 否 | 前端经 Nginx 走**容器内部网络**反代(`proxy_pass http://backend:8082`),不经过宿主机端口 |
| db | `127.0.0.1:3307` | ❌ 否 | 数据库不应暴露;本机仍可用客户端连 3307 调试 |
后端和数据库绑定在 `127.0.0.1` 是**有意的安全设置**,只允许本机访问。若你临时需要让别的机器直连后端 API 调试,把 `docker-compose.yml` 里对应那行改回 `"8082:8082"`,再执行 `docker compose up -d`(改完记得改回去)。
#### 手机打不开时怎么查
1. **确认同一个 WiFi**:手机和电脑必须是同一个 SSID。
2. **WiFi 的客户端隔离(AP 隔离)**:单位、公共场所的网络常开启此功能,导致设备之间无法互访。这属于网络策略,与本项目无关 —— 用手机开热点让电脑连上试一次即可确认。
3. **Windows 防火墙**:需放行 80 端口入站。Docker Desktop 安装时会按其网络类别自动添加放行规则,若仍不通,用管理员 PowerShell 临时加一条:
```powershell
New-NetFirewallRule -DisplayName "WMMS 80" -Direction Inbound -LocalPort 80 -Protocol TCP -Action Allow
# 测试完删除:Remove-NetFirewallRule -DisplayName "WMMS 80"
```
4. **IP 会变**:`192.168.x.x` 由 DHCP 分配,路由器重启后可能变化。想长期使用,建议在路由器上给这台电脑做静态 IP 绑定。
> ⚠️ 数据库使用默认密码 `wmms1234`,后端 API 也没有额外的访问控制,因此**不要把 8082 / 3307 暴露到公网**。
### 默认用户
| 用户名 | 密码 | 角色 |
|--------|------|------|
| admin | admin123 | 管理员 |
| user | user123 | 普通用户 |
## 常用命令
```bash
# 查看日志
docker-compose logs -f
# 查看后端日志
docker-compose logs -f backend
# 停止服务
docker-compose down
# 重新构建并启动
docker-compose up -d --build
# 删除所有数据(谨慎操作)
docker-compose down -v
```
## 数据持久化
- **MySQL数据**: `mysql_data` Docker volume
- **上传文件**: `uploads_data` Docker volume
### ⚠️ 数据卷复用会导致表结构落后于代码
MySQL 官方镜像**只在数据目录为空时**才执行 `/docker-entrypoint-initdb.d/` 下的脚本。也就是说 `scripts/init.sql` **只在 `mysql_data` 卷第一次创建时执行一次**;只要卷还在,后续 `docker compose up -d` 一律直接复用旧数据,`init.sql` 完全不执行。
`docker compose down` **不带 `-v` 时卷会保留**,所以改过 schema 之后重新部署,新代码会跑在旧表结构上。典型症状是**容器全部 healthy、日志干净,但部分接口返回 500**:
```
Error 1054 (42S22): Unknown column 'inbound_no' in 'field list'
```
**部署前先确认现有表结构**:
```bash
docker compose exec db mysql -uroot -pwmms1234 -e "SHOW COLUMNS FROM inbound_orders; SHOW COLUMNS FROM outbound_orders; SHOW COLUMNS FROM material_categories;" wmms
```
将实际字段与当前 `scripts/init.sql` 对比。数据卷的创建时间只能作为排查线索,不能证明表结构是否一致。
**方式一:清空重建(推荐,最简单可靠)**
```bash
docker compose down -v && docker compose up -d --build
```
`-v` 会删除 `mysql_data` 和 `uploads_data` 两个卷,**库中数据全部丢失**。执行前务必确认没有需要保留的业务数据,必要时先备份:
```bash
docker compose exec db mysqldump -uroot -pwmms1234 --default-character-set=utf8mb4 wmms > backup.sql
```
**方式二:保留数据并更新结构**
需要保留业务数据时,先备份数据库,再根据实际表结构与 `scripts/init.sql` 的差异编写并审核增量 SQL,在备份副本上验证后执行。
当前 `scripts/init.sql` 用于空库首次初始化,已包含出入库单号、操作人、备注、分类说明、6 个大类和 28 个子类,以及对应编码规则。库存预警阈值为 0 是有效配置,新库无需清理历史规则。不要将完整初始化脚本直接用于已有业务数据的数据库。
## 环境变量
| 变量 | 默认值 | 说明 |
|------|--------|------|
| DB_DSN | root:wmms1234@tcp(db:3306)/wmms?charset=utf8mb4&parseTime=true | 数据库连接字符串 |
| GIN_MODE | release | Gin 运行模式 |
## 手动构建
```bash
# 构建后端
docker build -t wmms-backend .
# 构建前端
cd frontend
docker build -t wmms-frontend .
# 启动
docker-compose up -d
```
## 故障排查
### 端口冲突
如果 80 或 3306 端口被占用:
```bash
# 查看端口占用
netstat -ano | findstr ":80"
netstat -ano | findstr ":3306"
# 修改 docker-compose.yml 中的端口映射
```
### 数据库连接失败
```bash
# 检查数据库是否就绪
docker-compose logs db
# 等待数据库启动完成(约10秒)
```
### 接口返回 500:Unknown column 'xxx'
**症状**:容器状态全部 healthy,`docker compose logs` 也看不到异常,但某些接口返回 500,例如:
```
Error 1054 (42S22): Unknown column 'description' in 'field list'
```
**原因**:`mysql_data` 卷是旧的,`init.sql` 没有执行,表结构落后于当前代码。详见上文《数据持久化 → ⚠️ 数据卷复用会导致表结构落后于代码》。
**确认**:
```bash
docker compose exec db mysql -uroot -pwmms1234 -e "SHOW COLUMNS FROM material_categories;" wmms
```
检查报错涉及的表是否缺少字段,并与当前 `scripts/init.sql` 对比。
**解决**:确认数据库和上传文件均无需保留后,可执行 `docker compose down -v && docker compose up -d --build` 重建;需要保留数据时,先备份,再按实际结构差异准备并验证增量 SQL。
### 其他排查技巧
**哪些表结构会不一致?** 直接在容器里对比:
```bash
# 看当前库到底建了哪些表和列
docker compose exec db mysql -uroot -pwmms1234 -e "SHOW TABLES;" wmms
docker compose exec db mysql -uroot -pwmms1234 -e "SHOW COLUMNS FROM inbound_orders;" wmms
```
### 查看容器内部
```bash
# 进入后端容器
docker exec -it wmms-backend sh
# 进入数据库容器
docker exec -it wmms-db mysql -u root -p
```