为减少仓库噪声和重复规则,整理当前开发入口并移除已废弃资料。 - 精简根 AGENTS,补充四个应用规则与 README,统一规范入口 - 归整部署文件、SOP 原稿和参考资源,修正迁移后的脚本路径 - 取消虚拟环境、工具状态、业务导出及备份的跟踪,本机所需原件保留 - 移除停用的 graphify 配置、脚本与产物 - 删除历史业务文档、执行计划、OpenSpec 业务变更和移动 UI 原型 - 清理失效引用,历史细胞产品导入改为必须显式指定 --file 验证:git diff --cached --check、OpenSpec 严格校验、导入参数隔离检查 3/3 通过; 迁移文件完整性和现行链接已核对。未执行部署、业务数据导入或服务启停。
502 lines
15 KiB
Markdown
502 lines
15 KiB
Markdown
# 中科兴皖 Docker 部署说明
|
||
|
||
> 适用对象:甲方运维人员
|
||
> 部署方式:**预构建应用镜像 + compose**(交付包**不含**前后端源码;基础镜像 MySQL/Redis/MinIO 由甲方联网拉取)
|
||
> 对外端口:**8112**
|
||
|
||
---
|
||
|
||
## 1. 环境要求
|
||
|
||
| 项 | 要求 |
|
||
|----|------|
|
||
| 操作系统 | Linux x86_64(推荐 Ubuntu 22.04 / CentOS 7+) |
|
||
| Docker | ≥ 24.0 |
|
||
| Docker Compose | v2(`docker compose` 子命令) |
|
||
| 网络 | 可访问 Docker Hub 或已配置国内镜像加速 |
|
||
| 硬件 | 建议 4 核 CPU、8 GB 内存、磁盘 ≥ 50 GB |
|
||
| 端口 | 宿主机 **8112** 未被占用 |
|
||
|
||
验证:
|
||
|
||
```bash
|
||
docker --version
|
||
docker compose version
|
||
docker info | grep -A2 "Registry Mirrors" # 建议已配置国内加速
|
||
```
|
||
|
||
---
|
||
|
||
## 1.1 Docker 镜像加速(国内强烈建议)
|
||
|
||
**要配。** 与 pip / npm 镜像不是一回事:
|
||
|
||
| 类型 | 作用 | 本项目中谁需要 |
|
||
|------|------|----------------|
|
||
| **Docker Registry 镜像** | 加速 `docker pull` / 构建时拉 `python:3.9-slim` 等 | **发版方打包** + **甲方首次 `compose up`** |
|
||
| **PyPI / npm 镜像** | 构建镜像时 `pip install`、`pnpm install` | 仅发版方打包(已写在 Dockerfile 里) |
|
||
|
||
甲方 `docker load` 只导入你们提供的 `zkxw-backend` / `zkxw-web`;首次启动仍会 **pull** 例如:
|
||
|
||
- `mysql:5.7.36`、`redis:7-alpine`、`minio/minio`、`minio/mc`
|
||
|
||
发版方在 Mac 上 `docker build` 时也要拉 `python:3.9-slim`、`node:20-alpine`、`nginx:1.27-alpine`。
|
||
|
||
### macOS(Docker Desktop)
|
||
|
||
**Settings → Docker Engine**,在 JSON 中增加(示例,任选可用加速地址):
|
||
|
||
```json
|
||
{
|
||
"registry-mirrors": [
|
||
"https://docker.1ms.run",
|
||
"https://docker.m.daocloud.io"
|
||
]
|
||
}
|
||
```
|
||
|
||
保存后 **Apply & Restart**。你本机若 `docker info` 已显示 `Registry Mirrors: https://docker.1ms.run/`,说明已配置,无需重复。
|
||
|
||
### Linux 云主机(发版 / 甲方)
|
||
|
||
编辑 `/etc/docker/daemon.json`:
|
||
|
||
```json
|
||
{
|
||
"registry-mirrors": [
|
||
"https://docker.1ms.run",
|
||
"https://docker.m.daocloud.io"
|
||
]
|
||
}
|
||
```
|
||
|
||
然后:
|
||
|
||
```bash
|
||
sudo systemctl daemon-reload
|
||
sudo systemctl restart docker
|
||
```
|
||
|
||
### 说明
|
||
|
||
- 镜像加速由 Docker 守护进程配置,**写进 Dockerfile 无效**。
|
||
- 公司若已有 **阿里云 ACR 个人版加速地址**,优先用官方提供的专属 URL。
|
||
- 应用镜像 `zkxw-*` 来自交付包 `docker load`,**不经过** Hub 拉取。
|
||
- 若 `docker.1ms.run` 拉取 `node`/`nginx` 报 **not found**,前端构建 Dockerfile 已默认改用 `docker.m.daocloud.io/library/...`;或在 Docker Engine 中把 DaoCloud 放在 `registry-mirrors` 第一条。
|
||
|
||
---
|
||
|
||
## 2. 交付方打包(我方,含源码仓库)
|
||
|
||
在**己方**开发机或 CI(有完整 Git 仓库)执行:
|
||
|
||
```bash
|
||
./scripts/package-docker-deploy.sh # 默认日期版本
|
||
./scripts/package-docker-deploy.sh v1.0.0 # 指定版本号
|
||
./scripts/package-docker-deploy.sh v1.1.0 # 含 mobile-oa-h5(/oa-h5/)+ 微信开关
|
||
```
|
||
|
||
`package-docker-deploy.sh` 固定构建 **`linux/amd64`** 镜像(适配甲方 Linux x86 云主机)。仅在对方确认为 ARM 云主机时,发版前改脚本中的 `DOCKER_PLATFORM` 为 `linux/arm64`。
|
||
|
||
脚本会:
|
||
|
||
1. 本地 `docker build` 生成 `zkxw-backend:<版本>`、`zkxw-web:<版本>`(**web 镜像内含 web-admin + `/oa-h5/`(mobile-oa-h5)**)
|
||
2. `docker save` 导出为 `images/zkxw-app-images.tar`
|
||
3. 打包 compose、`.env.example`、`docs/sql/zkxw.sql`(**不含** `backend/`、`web-admin/`、`mobile-oa-h5/` 源码)
|
||
|
||
产物:`dist/zkxw-docker-deploy-<版本>.tar.gz`
|
||
|
||
仅重新构建镜像、不重新打交付包时:
|
||
|
||
```bash
|
||
./scripts/build-docker-images.sh v1.0.0
|
||
```
|
||
|
||
发版方在仓库内从源码本地调试构建:
|
||
|
||
```bash
|
||
cd deploy/docker
|
||
docker compose -f docker-compose.yml -f docker-compose.build.yml build
|
||
docker compose up -d
|
||
```
|
||
|
||
**交付前自检:**
|
||
|
||
```bash
|
||
tar -xzf dist/zkxw-docker-deploy-*.tar.gz -C /tmp
|
||
cd /tmp/zkxw-docker-deploy-*
|
||
docker load -i images/zkxw-app-images.tar
|
||
cd deploy/docker && cp .env.example .env
|
||
docker compose up -d
|
||
curl -s http://127.0.0.1:8112/health
|
||
```
|
||
|
||
---
|
||
|
||
## 3. 交付包目录说明(甲方收到的内容)
|
||
|
||
```text
|
||
zkxw-docker-deploy-<版本>/
|
||
├── images/
|
||
│ └── zkxw-app-images.tar # 预构建前后端镜像(无源码)
|
||
├── deploy/docker/
|
||
│ ├── docker-compose.yml
|
||
│ ├── .env.example # 含 ZKXW_*_IMAGE 版本号
|
||
│ └── mysql/init/
|
||
├── docs/sql/zkxw.sql # 首次部署自动建库用
|
||
├── 部署说明.md
|
||
├── 部署指导手册.html # 客户安装手册(浏览器打开,推荐交付)
|
||
└── VERSION.txt
|
||
```
|
||
|
||
**不包含**:`backend/`、`web-admin/`、`mobile-oa-h5/`、Dockerfile、`.vue` / `.py` 业务源码。
|
||
|
||
数据库脚本 `zkxw.sql` 仅为表结构与基线数据,非应用源代码。
|
||
|
||
Nginx 反代配置已打入 `zkxw-web` 镜像(含管理端 `/` 与 OA H5 `/oa-h5/`),无需单独配置。
|
||
|
||
---
|
||
|
||
## 3.1 从 v1.0.0 增量升级到 v1.1.0(小程序 OA H5 + 微信配置)
|
||
|
||
适用:已在运行 `zkxw-backend:v1.0.0` / `zkxw-web:v1.0.0`,数据卷保留,**不重装** MySQL/Redis/MinIO。
|
||
|
||
典型目录(以现网调查为准):
|
||
|
||
```text
|
||
/opt/zkxw/zkxw-docker-deploy-v1.0.0/deploy/docker
|
||
```
|
||
|
||
### 发版方
|
||
|
||
```bash
|
||
./scripts/package-docker-deploy.sh v1.1.0
|
||
# 产物:dist/zkxw-docker-deploy-v1.1.0.tar.gz
|
||
```
|
||
|
||
### 内网机(192.168.200.24)运维
|
||
|
||
```bash
|
||
# 1) 用户自行上传 tar 到内网机后解压(路径自定,示例)
|
||
cd /opt/zkxw
|
||
tar -xzf zkxw-docker-deploy-v1.1.0.tar.gz
|
||
docker load -i zkxw-docker-deploy-v1.1.0/images/zkxw-app-images.tar
|
||
|
||
# 2) 改现网 .env
|
||
cd /opt/zkxw/zkxw-docker-deploy-v1.0.0/deploy/docker
|
||
# 只改镜像 tag(示例):
|
||
# ZKXW_BACKEND_IMAGE=zkxw-backend:v1.1.0
|
||
# ZKXW_WEB_IMAGE=zkxw-web:v1.1.0
|
||
#
|
||
# 微信/小程序:新交付包 .env.example 打包时会从发版机注入;
|
||
# - 推荐:保留现网 MYSQL/SECRET/MINIO 密码,把包内 WX_MP_* / WXPAY_* 段合并进来
|
||
# - 切勿用「仅含 change-me 库口令」的全新 .env 整文件覆盖现网,否则连不上原数据库
|
||
|
||
# 3) 只滚动应用(数据卷不动)
|
||
docker compose up -d backend web
|
||
|
||
# 4) 本机验收
|
||
curl -sI http://127.0.0.1:8112/ | head -5
|
||
curl -sI http://127.0.0.1:8112/oa-h5/ | head -5
|
||
curl -s http://127.0.0.1:8112/health
|
||
```
|
||
|
||
### 公网网关 39.102.214.125(xwyd.zkxw.cn → 112.30.112.8:60001)
|
||
|
||
现网 `xwyd.zkxw.cn` 对 `/` 做整站 `proxy_pass` 到内网 `60001`,**一般无需改 Nginx**:
|
||
|
||
- `https://xwyd.zkxw.cn/` → 管理端
|
||
- `https://xwyd.zkxw.cn/oa-h5/` → OA H5(新)
|
||
- `https://xwyd.zkxw.cn/api/`、`/minio/zkxw/` → 随同反代
|
||
|
||
内网 `112.30.112.8:60001 → 192.168.200.24:8112` 映射**保持不动**。升级后公网验收:
|
||
|
||
```bash
|
||
curl -skI https://xwyd.zkxw.cn/oa-h5/ | head -5
|
||
```
|
||
|
||
若 `/oa-h5/` 404 而本机 `8112` 正常,再查网关是否对路径做了白名单(当前配置为整站反代则无需改)。
|
||
|
||
---
|
||
|
||
## 4. 甲方服务器上线步骤
|
||
|
||
```bash
|
||
# 1) 安装 Docker + Compose(若未安装)
|
||
docker --version && docker compose version
|
||
|
||
# 2) 上传并解压交付包
|
||
mkdir -p /opt/zkxw && cd /opt/zkxw
|
||
tar -xzf zkxw-docker-deploy-*.tar.gz
|
||
cd zkxw-docker-deploy-*
|
||
|
||
# 3) 导入应用镜像(前后端,无源码)
|
||
docker load -i images/zkxw-app-images.tar
|
||
docker images | grep zkxw-
|
||
|
||
# 4) 配置并启动
|
||
cd deploy/docker
|
||
cp .env.example .env
|
||
vi .env # 改密码;确认 ZKXW_BACKEND_IMAGE / ZKXW_WEB_IMAGE 与 load 的 tag 一致
|
||
|
||
# 5) 启动(会拉取 mysql:5.7.36、redis、minio 等基础镜像,无需 --build)
|
||
docker compose up -d
|
||
|
||
# 6) 查看进度(首次 MySQL 导入约 1~3 分钟)
|
||
docker compose ps
|
||
docker compose logs -f mysql
|
||
docker compose logs -f backend
|
||
|
||
# 7) 验收
|
||
curl -s http://127.0.0.1:8112/health
|
||
# 浏览器打开 http://<服务器IP>:8112/ 账号 admin / 111111
|
||
```
|
||
|
||
防火墙 / 安全组放行 **TCP 8112**。
|
||
|
||
| 地址 | 说明 |
|
||
|------|------|
|
||
| `http://<服务器IP>:8112/` | Web 管理端 |
|
||
| `http://<服务器IP>:8112/health` | 健康检查 |
|
||
| `http://<服务器IP>:8112/docs` | Swagger |
|
||
|
||
默认账号:`admin` / `111111`(首次登录后请修改)。
|
||
|
||
默认 `COMPOSE_PROFILES=full`:自带 MySQL、Redis、MinIO,首次启动自动导入 `docs/sql/zkxw.sql`。
|
||
|
||
**Mac(M 芯片)本地试跑**:`mysql:5.7.36` 无 arm64 包,compose 已统一 `platform: linux/amd64`(模拟运行,会慢一些)。**不必**为 Mac 重新打 `zkxw-app-images.tar`。
|
||
|
||
---
|
||
|
||
## 5. 服务架构
|
||
|
||
```text
|
||
浏览器 :8112
|
||
└── web(Nginx + 前端静态)
|
||
├── /api/* → backend:8111(FastAPI)
|
||
└── /minio/zkxw/* → minio:9000(附件,仅容器内网络)
|
||
|
||
backend → mysql:3306(业务库 zkxw)
|
||
→ redis:6379(会话)
|
||
→ minio:9000(对象存储)
|
||
|
||
minio-init(首次/每次 up 时执行一次):自动创建 `MINIO_BUCKET`(默认 zkxw),并设置 **匿名可读(download)**,供 Nginx `/minio/zkxw/` 反代访问附件;上传仍由后端 API 鉴权后写入。
|
||
```
|
||
|
||
**重要**:MySQL、Redis、MinIO **不映射宿主机端口**,只在 Docker 内部网络通信,**不会**与甲方已有 3306/6379/9000 服务冲突。对外仅开放 **8112**。
|
||
|
||
**API 传输**:Docker 交付默认**关闭**前后端 API 加解密(`API_ENCRYPT_ENABLED=false` / `VITE_API_ENCRYPT_ENABLED=false`),请求与响应为明文 JSON。若需启用,须同时改 `.env` 与 `web-admin/.env.docker` 后重建 `backend`、`web` 镜像。
|
||
|
||
---
|
||
|
||
## 6. 两种部署 Profile
|
||
|
||
通过 `.env` 中 `COMPOSE_PROFILES` 切换。
|
||
|
||
### 6.1 `full`(默认,全栈)
|
||
|
||
```env
|
||
COMPOSE_PROFILES=full
|
||
```
|
||
|
||
启动:MySQL + Redis + MinIO + 后端 + 前端。
|
||
|
||
`.env` 中使用 Docker 服务名:
|
||
|
||
```env
|
||
DATABASE_URL=mysql+pymysql://root:<密码>@mysql:3306/zkxw
|
||
REDIS_HOST=redis
|
||
MINIO_ENDPOINT=minio:9000
|
||
MINIO_BASE_URL=/minio/zkxw
|
||
```
|
||
|
||
### 6.2 `app`(仅应用,连接甲方已有中间件)
|
||
|
||
甲方已有 MySQL、Redis、MinIO 时使用:
|
||
|
||
```env
|
||
COMPOSE_PROFILES=app
|
||
|
||
DATABASE_URL=mysql+pymysql://user:pass@10.0.0.10:3306/zkxw
|
||
REDIS_HOST=10.0.0.11
|
||
REDIS_PORT=6379
|
||
MINIO_ENDPOINT=10.0.0.12:9000
|
||
MINIO_ACCESS_KEY=...
|
||
MINIO_SECRET_KEY=...
|
||
MINIO_BUCKET=zkxw
|
||
MINIO_BASE_URL=http://10.0.0.12:9000/zkxw
|
||
```
|
||
|
||
```bash
|
||
docker compose up -d --build
|
||
```
|
||
|
||
**注意**:若 MinIO 不在 Docker 网络内,需同步修改 `web-admin/.env.docker` 中的 `VITE_MINIO_BASE_URL` 并重新构建 web 镜像;或保留 MinIO 容器见下节。
|
||
|
||
### 6.3 `app,storage`(外部库 + 自带 MinIO)
|
||
|
||
已有 MySQL/Redis,但希望 MinIO 仍由本 compose 提供:
|
||
|
||
```env
|
||
COMPOSE_PROFILES=app,storage
|
||
```
|
||
|
||
`.env` 中 `DATABASE_URL`、`REDIS_HOST` 指向甲方地址;`MINIO_ENDPOINT` 仍用 `minio:9000`。
|
||
|
||
---
|
||
|
||
## 7. 常用运维命令
|
||
|
||
```bash
|
||
cd deploy/docker
|
||
|
||
# 停止
|
||
docker compose down
|
||
|
||
# 重启
|
||
docker compose restart
|
||
|
||
# 仅重建后端
|
||
docker compose up -d --build backend
|
||
|
||
# 仅重建前端
|
||
docker compose up -d --build web
|
||
|
||
# 查看日志
|
||
docker compose logs -f backend
|
||
docker compose logs -f web
|
||
|
||
# 进入后端容器
|
||
docker compose exec backend bash
|
||
```
|
||
|
||
---
|
||
|
||
## 8. 数据持久化与备份
|
||
|
||
Docker 卷(`docker volume ls | grep zkxw`):
|
||
|
||
| 卷名 | 内容 |
|
||
|------|------|
|
||
| `zkxw_mysql_data` | MySQL 数据 |
|
||
| `zkxw_redis_data` | Redis 持久化 |
|
||
| `zkxw_minio_data` | 附件对象 |
|
||
| `zkxw_backend_uploads` | 本地存储模式下的上传目录 |
|
||
|
||
MySQL 备份示例:
|
||
|
||
```bash
|
||
docker compose exec mysql mysqldump -uroot -p zkxw > zkxw_backup.sql
|
||
```
|
||
|
||
**警告**:`docker compose down -v` 会删除所有卷,导致数据丢失。
|
||
|
||
---
|
||
|
||
## 9. 升级发版
|
||
|
||
```bash
|
||
cd /opt/zkxw/zkxw-docker-deploy-<新版本>
|
||
|
||
# 1) 备份数据库与 MinIO 卷
|
||
# 2) 导入新应用镜像
|
||
docker load -i images/zkxw-app-images.tar
|
||
|
||
# 3) 更新 deploy/docker/.env 中 ZKXW_BACKEND_IMAGE、ZKXW_WEB_IMAGE
|
||
cd deploy/docker
|
||
docker compose up -d
|
||
|
||
# 4) 验证
|
||
curl -s http://127.0.0.1:8112/health
|
||
```
|
||
|
||
若仅有数据库结构变更,由交付方提供增量 SQL,**不要**删除已有 `mysql_data` 卷。
|
||
|
||
---
|
||
|
||
## 10. 环境变量要点
|
||
|
||
| 变量 | 说明 |
|
||
|------|------|
|
||
| `HTTP_PORT` | 对外端口,默认 8112 |
|
||
| `MYSQL_ROOT_PASSWORD` | MySQL root 密码(full profile) |
|
||
| `DATABASE_URL` | 须与 MySQL 账号密码一致 |
|
||
| `SECRET_KEY` | JWT 密钥,生产必须改为长随机串 |
|
||
| `API_ENCRYPT_ENABLED` | Docker 交付默认 `false`(前后端 API 不加密) |
|
||
| `MINIO_*` | 对象存储;bucket 由 minio-init 自动创建并设为匿名下载(供 `/minio/zkxw/` 访问) |
|
||
|
||
修改 `.env` 后:
|
||
|
||
```bash
|
||
docker compose up -d
|
||
docker compose restart backend
|
||
```
|
||
|
||
修改 `web-admin/.env.docker` 后须重建 web:
|
||
|
||
```bash
|
||
docker compose up -d --build web
|
||
```
|
||
|
||
---
|
||
|
||
## 11. 常见问题
|
||
|
||
### 8112 无法访问
|
||
|
||
- 检查防火墙 / 安全组是否放行 8112
|
||
- `docker compose ps` 确认 `web` 为 running
|
||
- `docker compose logs web`
|
||
|
||
### `/api` 返回 502
|
||
|
||
- 后端未就绪:`docker compose logs backend`
|
||
- MySQL 初始化未完成(首次启动约 1~3 分钟):`docker compose logs mysql`
|
||
|
||
### 数据库初始化失败需重来
|
||
|
||
仅**首次部署失败**且可接受清空数据时:
|
||
|
||
```bash
|
||
docker compose down -v
|
||
docker compose up -d
|
||
```
|
||
|
||
### 附件无法访问
|
||
|
||
- 确认 `STORAGE_TYPE=minio`
|
||
- `docker compose logs minio-init`(应看到 bucket 创建与 `anonymous set download` 成功)
|
||
- 浏览器 Network 中附件 URL 应为 `/minio/zkxw/...`
|
||
- 若 bucket 在加入匿名策略前已存在,可手动执行:`docker compose run --rm minio-init` 或删除 `minio_data` 卷后重新 `up`(会清空附件)
|
||
|
||
### 拉取镜像慢或失败
|
||
|
||
见上文 **§1.1 Docker 镜像加速**,配置 `registry-mirrors` 后重试 `docker compose up -d`。
|
||
|
||
### 发版方打包时 pip / pnpm 很慢或超时
|
||
|
||
- 已默认 **阿里云 PyPI** + **npmmirror**,并启用 BuildKit 缓存。
|
||
- 默认 **npmmirror**(`https://registry.npmmirror.com`)。**国内 Intel / Linux 机器不要设 `NPM_REGISTRY=https://registry.npmjs.org`**,该地址在国内常 ETIMEDOUT。
|
||
- 若 npmmirror 不稳定,可换其它国内源:
|
||
```bash
|
||
NPM_REGISTRY=https://mirrors.cloud.tencent.com/npm/ ./scripts/package-docker-deploy.sh v1.0.0
|
||
# 或
|
||
NPM_REGISTRY=https://repo.huaweicloud.com/repository/npm/ ./scripts/package-docker-deploy.sh v1.0.0
|
||
```
|
||
- 安装 pnpm 失败时 Dockerfile 会自动回退为 tarball 直装;`pnpm install` 出现 ETIMEDOUT 时会重试,日志可能长时间不动,**不要误按 Ctrl+C**。
|
||
- **在 Mac(M 芯片)上交叉构建 `linux/amd64` 很慢**(后端 pip 常见 15~40 分钟);**Intel Linux 同架构构建**通常 5~15 分钟,推荐在发版机上直接执行 `./scripts/package-docker-deploy.sh v1.0.0`(无需设 `NPM_REGISTRY`)。
|
||
|
||
默认已使用阿里云 PyPI(`mirrors.aliyun.com`)。若需改用清华源:
|
||
|
||
```bash
|
||
PIP_INDEX_URL=https://pypi.tuna.tsinghua.edu.cn/simple \
|
||
PIP_TRUSTED_HOST=pypi.tuna.tsinghua.edu.cn \
|
||
./scripts/package-docker-deploy.sh v1.0.0
|
||
```
|
||
|
||
---
|
||
|
||
## 12. 与手工部署的关系
|
||
|
||
本方案与 `deploy/test/README.md` 中「Nginx 10001 + 同域 `/api` 反代后端 10002」拓扑一致。应用以**预构建镜像**交付,甲方执行 `docker load` + `docker compose up -d` 即可,无需源码与 `pnpm`/`pip` 构建环境。
|