Files
zkxw/deploy/docker/README.md
T
2026-06-04 12:57:59 +08:00

436 lines
13 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 部署说明
> 适用对象:甲方运维人员
> 部署方式:**预构建应用镜像 + 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 # 指定版本号
```
`package-docker-deploy.sh` 固定构建 **`linux/amd64`** 镜像(适配甲方 Linux x86 云主机)。仅在对方确认为 ARM 云主机时,发版前改脚本中的 `DOCKER_PLATFORM` 为 `linux/arm64`。
脚本会:
1. 本地 `docker build` 生成 `zkxw-backend:<版本>`、`zkxw-web:<版本>`
2. `docker save` 导出为 `images/zkxw-app-images.tar`
3. 打包 compose、`.env.example`、`docs/sql/zkxw.sql`(**不含** `backend/`、`web-admin/` 源码)
产物:`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/`、Dockerfile、`.vue` / `.py` 业务源码。
数据库脚本 `zkxw.sql` 仅为表结构与基线数据,非应用源代码。
Nginx 反代配置已打入 `zkxw-web` 镜像,无需单独配置。
---
## 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 缓存。
- 若前端构建在 `corepack prepare pnpm@...` 报错(请求 `registry.npmjs.org` 失败),请更新到含 `COREPACK_NPM_REGISTRY` 的 Dockerfile,或手动指定:
```bash
NPM_REGISTRY=https://registry.npmmirror.com ./scripts/package-docker-deploy.sh v1.0.0
```
- **在 Mac(M 芯片)上交叉构建 `linux/amd64` 很慢**(后端 pip 常见 15~40 分钟),日志会长时间不动,**不要误按 Ctrl+C**。
- **推荐**:把仓库放到 **Linux x86 云主机**(与甲方同架构),在该机器执行 `./scripts/package-docker-deploy.sh`,通常 5~15 分钟完成。
默认已使用阿里云 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. 与手工部署的关系
本方案与 `测试环境部署/README.md` 中「Nginx 8112 + 同域 `/api` 反代」拓扑一致。应用以**预构建镜像**交付,甲方执行 `docker load` + `docker compose up -d` 即可,无需源码与 `pnpm`/`pip` 构建环境。