Files
Nexus/docs/design/plans/2026-06-04-1panel-docker-production.md
T
Nexus Deploy 7b33b745a0 feat(deploy): add 1Panel Docker one-click install script
Automates clone, docker/.env.prod, compose up, and health check for 2C8G prod stack.
2026-06-05 22:52:44 +08:00

366 lines
11 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.
# 1Panel + Docker Compose 生产迁移计划
| 项 | 内容 |
|----|------|
| 日期 | 2026-06-04 |
| 状态 | **计划** — 待在新 VPS 或同机试跑后执行 |
| 目标 | 脱离宝塔,用 **1Panel 管机 + Docker Compose 跑 Nexus 全栈** |
| 关联 | [2026-06-03-docker.md](./2026-06-03-docker.md) · `docker-compose.yml` · `deploy/nginx_https.conf` |
---
## 1. 背景与目标
### 1.1 现状
- 生产:`47.254.123.106` / `api.synaglobal.vip`,宝塔 + 裸机 Git + Supervisor + Nginx
- 代码:Gitea `main` @ `811eb97+`
- 本地:已有 `docker-compose.yml`dev/staging),**不含前端构建**`Dockerfile` 依赖预构建 `web/app/`
### 1.2 目标架构
```mermaid
flowchart TB
subgraph internet [Internet]
Users[浏览器 / Agent]
Agents[2000+ Agent]
end
subgraph vps [VPS + 1Panel]
OP[OpenResty HTTPS]
subgraph compose [Docker Compose prod]
NX[nexus:8600]
MY[(mysql:3306)]
RD[(redis:6379)]
end
Vol1[(mysql-data)]
Vol2[(redis-data)]
Vol3[(nexus-state .env)]
end
Users --> OP
Agents --> OP
OP -->|127.0.0.1:8600| NX
NX --> MY
NX --> RD
MY --> Vol1
RD --> Vol2
NX --> Vol3
```
**原则**
- 1Panel:防火墙、SSL、备份、终端、Compose 编排 UI
- Nexus**单 Compose 栈**MySQL + Redis + API/静态 SPA
- OpenResty**只反代到 `127.0.0.1:8600`**(静态由 FastAPI `StaticFiles` 提供,无需双份 `web/app`
- **密钥不动**`NEXUS_SECRET_KEY` / `NEXUS_API_KEY` / `NEXUS_ENCRYPTION_KEY` 从宝塔 `.env` 原样迁入
---
## 2. 涉及文件清单
| 文件 | 作用 |
|------|------|
| `Dockerfile.prod` | 多阶段:Node 构建前端 + Python 镜像 |
| `docker/docker-compose.prod.yml` | 生产 Compose(不暴露 DB 端口、仅绑定 127.0.0.1:8600 |
| `docker/.env.prod.example` | 生产环境变量模板(不入 Git) |
| `deploy/1panel/openresty-nexus.conf.example` | 1Panel 网站反代参考 |
| `docs/project/production-verification-checklist.md` | L5 验收 |
**本计划不修改** `docker-compose.yml`(继续服务本地 dev)。
---
## 3. 服务器前置条件
| 项 | 要求 |
|----|------|
| OS | Ubuntu 22.04+ / Debian 11+ |
| 内存 | **≥ 4GB**MySQL + Redis + Nexus + 1Panel |
| 磁盘 | ≥ 40GB(视 Agent 历史与日志) |
| 域名 | `api.synaglobal.vip` A 记录指向本机 |
| 1Panel | [官方安装脚本](https://1panel.cn/docs/installation/) 最新稳定版 |
| Docker | 由 1Panel 安装或自带 |
**建议**:在新 VPS 试跑通过后再切 DNS,宝塔旧机保留 24~48h 回滚窗口。
---
## 4. 实施步骤
### Phase 0 — 备份宝塔生产(必做)
在**旧宝塔机**执行:
```bash
# 1) 整库备份
mysqldump -u Nexus -p nexus > /tmp/nexus-$(date +%F).sql
# 2) 复制 .env(含不可改密钥)
cp /www/wwwroot/api.synaglobal.vip/.env /tmp/nexus.env.backup
# 3) 可选:web/data
tar czf /tmp/nexus-web-data.tar.gz -C /www/wwwroot/api.synaglobal.vip/web data
```
`nexus-*.sql``nexus.env.backup` 下载到本机安全位置(勿提交 Git)。
---
### Phase 1 — 安装 1Panel
```bash
curl -sSL https://resource.fit2cloud.com/1panel/package/quick_start.sh -o quick_start.sh
sudo bash quick_start.sh
```
记录面板地址、端口、管理员密码。
**安全**:改默认端口、开防火墙仅放行 22 / 443 / 面板端口。
---
### Phase 2 — 一键安装(推荐)
在 1Panel **终端**
```bash
export NEXUS_GITEA_TOKEN='你的Gitea令牌'
export NEXUS_DOMAIN='api.synaglobal.vip'
# 从宝塔迁机:
# export NEXUS_FROM_ENV='/www/wwwroot/api.synaglobal.vip/.env'
cd /opt/nexus 2>/dev/null && git pull || true
# 若尚未 clone,从任意目录:
curl -fsSL "http://66.154.115.8:3000/admin/Nexus/raw/branch/main/deploy/install-1panel-docker.sh" | bash
# 或已 clone 后:
# cd /opt/nexus && bash deploy/install-1panel-docker.sh --skip-clone
```
脚本:`deploy/install-1panel-docker.sh`clone → `.env.prod``compose up``/health`)。
### Phase 2b — 手工准备代码与生产 env(可选)
在 1Panel **终端**或 SSH
```bash
export NEXUS_ROOT=/opt/nexus
sudo mkdir -p "$NEXUS_ROOT"
sudo git clone http://66.154.115.8:3000/admin/Nexus.git "$NEXUS_ROOT"
cd "$NEXUS_ROOT"
git checkout main && git pull
```
创建 `docker/.env.prod`(从 `docker/.env.prod.example` 复制):
```bash
cp docker/.env.prod.example docker/.env.prod
chmod 600 docker/.env.prod
nano docker/.env.prod
```
**从宝塔 `.env` 原样填入**(不可改项):
- `NEXUS_SECRET_KEY`
- `NEXUS_API_KEY`
- `NEXUS_ENCRYPTION_KEY`
- `NEXUS_DATABASE_URL` → 改为 Compose 内网:`mysql+aiomysql://nexus:<密码>@mysql:3306/nexus`
- `NEXUS_REDIS_URL``redis://redis:6379/0`
- `NEXUS_CORS_ORIGINS``https://api.synaglobal.vip`
- `NEXUS_API_BASE_URL``https://api.synaglobal.vip`
MySQL 密码:可用宝塔库密码,或新设强密码并在导入后统一。
---
### Phase 3 — 构建并启动 Compose
```bash
cd /opt/nexus
docker compose -f docker/docker-compose.prod.yml --env-file docker/.env.prod up -d --build
docker compose -f docker/docker-compose.prod.yml ps
docker compose -f docker/docker-compose.prod.yml logs -f nexus
```
等待 MySQL healthy → Nexus entrypoint 写/恢复 `.env``/health``ok`
```bash
curl -s http://127.0.0.1:8600/health # 期望: ok
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8600/app/ # 期望: 200
```
---
### Phase 4 — 导入 MySQL 数据
```bash
# 上传 nexus-YYYY-MM-DD.sql 到 /tmp/
docker compose -f docker/docker-compose.prod.yml exec -T mysql \
mysql -uroot -p"$MYSQL_ROOT_PASSWORD" nexus < /tmp/nexus-2026-06-04.sql
```
验证:
```bash
docker compose -f docker/docker-compose.prod.yml exec mysql \
mysql -uroot -p"$MYSQL_ROOT_PASSWORD" -e "SELECT COUNT(*) FROM servers;"
```
**注意**:若库名/用户与宝塔不同,先建用户再导入;导入前建议空库或 `--force` 策略写进 runbook。
---
### Phase 5 — 1Panel OpenResty 反代 + SSL
1. 1Panel → **网站** → 创建站点 → 域名 `api.synaglobal.vip`
2. **HTTPS** → Let's Encrypt 一键申请
3. **反向代理** → 目标 `http://127.0.0.1:8600`(或「配置文件」粘贴 `deploy/1panel/openresty-nexus.conf.example` 内容)
要点(与 `deploy/nginx_https.conf` 对齐):
| 路径 | 行为 |
|------|------|
| `/api/` | 反代 API`proxy_read_timeout 300s` |
| `/ws/` | WebSocket`Upgrade` + `Connection upgrade`,超时 3600s |
| `/health` | 反代(或仅内网探测) |
| `/app/` | 反代(容器内 StaticFiles |
| `client_max_body_size` | `100m`(上传/推送) |
**WS 日志**:勿记录 query 中的 JWT(示例配置已用 `$uri``$args`)。
---
### Phase 6 — 在 1Panel 中托管 Compose(可选)
1Panel → **容器****编排** → 导入 `/opt/nexus/docker/docker-compose.prod.yml`
环境文件指向 `docker/.env.prod`,便于 UI 启停、看日志、备份卷。
---
### Phase 7 — L5 验收
`docs/project/production-verification-checklist.md`
| # | 检查 | 命令/预期 |
|---|------|-----------|
| 1 | HTTPS health | `curl -s https://api.synaglobal.vip/health``ok` |
| 2 | SPA | 浏览器 `/app/` 登录 |
| 3 | JWT | 未登录 `/api/servers/` → 401 |
| 4 | WebSocket | 仪表盘连接、告警刷新 |
| 5 | WebSSH | 终端页连一台子机 |
| 6 | Agent | 子机心跳仍指向同域名,Redis key 有 TTL |
| 7 | 后台任务 | 10min 内 MySQL 有心跳历史写入 |
记录到 `docs/reports/2026-06-04-1panel-migration-verification.md`(验收后创建)。
---
### Phase 8 — 切流量与下线宝塔
1. 确认新机 L5 全通过
2. DNS `api.synaglobal.vip` → 新 IP(若换机)
3. 观察 24hAgent、告警、Telegram
4. 宝塔机:停 `nexus` supervisor、保留备份后关机或降级为备用
---
## 5. 生产 Compose 与开发差异
| 项 | dev `docker-compose.yml` | prod `docker-compose.prod.yml` |
|----|--------------------------|--------------------------------|
| 构建 | `Dockerfile` | `Dockerfile.prod`(含前端 build |
| MySQL/Redis 端口 | 可映射宿主机 | **不映射**(仅 compose 网络) |
| Nexus 端口 | `8600:8600` | `127.0.0.1:8600:8600` |
| env 文件 | `docker/.env` | `docker/.env.prod` |
| 副本数 | 1 | **1**(后台任务 primary worker,勿随意扩多实例) |
| **2C8G 调优** | 无 | `mysql-prod-2c8g.cnf` + 容器内存上限 + pool 30/20 |
### 2C8G 资源预算(约)
| 组件 | 上限 |
|------|------|
| MySQL | 2G 容器 / `innodb_buffer_pool_size=1024M` |
| Redis | 384M 容器 / `maxmemory 256mb` |
| Nexus | 2G 容器 |
| 1Panel + OS | 其余 ~3G |
`docker/.env.prod` 建议包含:`NEXUS_DB_POOL_SIZE=30``NEXUS_DB_MAX_OVERFLOW=20`
---
## 6. 日常运维
### 6.1 升级(Gitea 有新 commit
```bash
cd /opt/nexus
git fetch && git reset --hard origin/main
docker compose -f docker/docker-compose.prod.yml --env-file docker/.env.prod up -d --build
curl -s http://127.0.0.1:8600/health
```
### 6.2 备份(1Panel 计划任务 + 手动)
| 对象 | 方式 |
|------|------|
| MySQL | 1Panel 数据库备份 或 `mysqldump` cron |
| 卷 `nexus-state` | 含持久化 `.env`,随卷备份 |
| 卷 `nexus-web-data` | `web/data/config.json` 等 |
### 6.3 日志
```bash
docker compose -f docker/docker-compose.prod.yml logs -f --tail=200 nexus
```
---
## 7. 回滚
| 场景 | 操作 |
|------|------|
| 新版本故障 | `git reset --hard <旧commit>` + `compose up -d --build` |
| 数据库误操作 | 恢复 Phase 0 的 `mysqldump` |
| 切 DNS 后严重故障 | DNS 指回宝塔旧 IP;旧机 `supervisorctl start nexus` |
| 密钥误改 | **禁止**随意重生成;从 `nexus.env.backup` 恢复 |
---
## 8. 风险与对策
| 风险 | 对策 |
|------|------|
| 密钥变更导致 Agent/凭据失效 | Phase 0/2 原样迁移三项 KEY |
| 多副本重复 schedule/retry | 生产 `replicas: 1` |
| 前端未进镜像 | 必须用 `Dockerfile.prod` |
| OpenResty WS 超时 | `/ws/` 读超时 ≥ 3600s |
| 内存不足 | ≥4GBMySQL 可限 `innodb_buffer_pool_size` |
| 1Panel 与 Compose 端口冲突 | Nexus 仅监听 127.0.0.1:8600 |
---
## 9. 与 Coolify 的关系
本方案 **不需要 Coolify**。若后续要 Git push 自动构建,可在 1Panel 稳定运行后,再评估:
- 1Panel 编排 + Gitea Webhook 触发 `compose up --build`
- 或同机加装 Coolify 仅负责 Nexus 镜像 CI
---
## 10. 验收标准(DoD
- [ ] 1Panel 安装且仅必要端口开放
- [ ] `docker compose -f docker/docker-compose.prod.yml ps` 三服务 healthy
- [ ] `https://api.synaglobal.vip/health``ok`
- [ ] 登录 + 文件管理 + WebSSH + 至少 1 台 Agent 心跳正常
- [ ] 宝塔已下线或不再承担流量
- [ ] changelog + 验收报告已写入
---
## 11. 变更记录
| 日期 | 说明 |
|------|------|
| 2026-06-04 | 初版:1Panel + Docker Compose 生产迁移 SSOT |