- /state 白名单脱敏;init-db db_port 修复;connection-check 后清空 redis_pass - install.html sessionStorage token 与无 token 友好提示 - nx update: 镜像 import 门控、健康失败自动回滚、PENDING=0 回写、卷双写 - Redis 容器改名密码迁移;备份失败默认 WARN;update.sh 管道 ROOT 回退
15 KiB
Nexus 6.0 — 1Panel + Docker 运维知识文档
| 项 | 内容 |
|---|---|
| 版本 | 2026-06-06 |
| 读者 | 运维、接续开发、AI Agent |
| 定位 | 1Panel 生产部署 SSOT(安装向导、网络、MySQL/Redis、日常 nx update) |
| 关联 | deploy/README-1panel.md · nexus-functional-development-guide.md · 2026-06-04-1panel-docker-production.md |
1. 架构总览
1.1 生产拓扑(1Panel)
flowchart LR
Internet --> OpenResty["OpenResty (host)"]
OpenResty -->|"127.0.0.1:8600"| Nexus["Nexus 容器"]
Nexus -->|"1Panel-mysql-xxxx:3306"| MySQL["1Panel MySQL"]
Nexus -->|"1Panel-redis-xxxx:6379"| Redis["1Panel Redis"]
Nexus --- VolState["卷 nexus-state (.env)"]
Nexus --- VolData["卷 nexus-web-data"]
MySQL --- Net["1panel-network"]
Redis --- Net
Nexus --- Net
铁律(1Panel 官方说明):
- 应用商店 MySQL/Redis 在
1panel-network上,容器间用 容器名 通信。 - 禁止在 Nexus 容器内用
127.0.0.1、localhost、host.docker.internal连 1Panel MySQL/Redis。 - OpenResty 在宿主机网络,反代目标为
http://127.0.0.1:8600。
1.2 仓库关键目录
| 路径 | 职责 |
|---|---|
server/ |
FastAPI 后端;api/install.py = 安装向导 API |
frontend/ |
Vue 3 SPA 源码(14 页) |
web/app/ |
构建产物;install.html 为独立静态页(Alpine.js,不经 Vite 路由) |
web/data/ |
运行时:config.json、1panel-hosts.json |
deploy/ |
1Panel 安装/升级、nx、验收与修复脚本 |
docker/ |
docker-compose.prod.yml、entrypoint.sh、.env.prod |
Dockerfile.prod |
多阶段:npm build + Python 镜像 |
1.3 两套 Compose
| 文件 | 服务 |
|---|---|
docker-compose.yml |
本地 dev:nexus + mysql + redis |
docker-compose.prod.yml |
生产:仅 nexus |
docker-compose.1panel.yml |
叠加:nexus 加入 1panel-network |
2. 启动模式与 .env 生命周期
2.1 安装模式 vs 正常模式
server/main.py 中 is_install_mode():运行时检测 /app/.env 是否存在。
| 模式 | 条件 | 可用能力 |
|---|---|---|
| 安装模式 | 无 /app/.env |
/api/install/*、/app/install.html、静态、/health |
| 正常模式 | 有完整 .env |
全 API、WebSocket、后台任务 |
2.2 配置存储四层
| 层级 | 位置 | 写入方 |
|---|---|---|
| Compose 环境 | 宿主机 docker/.env.prod |
nexus-1panel.sh install / generate_nexus_secrets.py |
| 应用根 | 容器 /app/.env |
安装向导步骤 3 init-db |
| 持久卷 | nexus-state → /var/lib/nexus/.env |
entrypoint.sh 退出时同步 |
| Web 数据 | nexus-web-data → /app/web/data/ |
config.json、1panel-hosts.json |
不可从 DB settings 覆盖:SECRET_KEY、API_KEY、ENCRYPTION_KEY、DATABASE_URL。
2.3 Docker 安装状态机
install --fresh
→ docker/.env.prod: NEXUS_INSTALL_WIZARD_PENDING=1 + 预生成三密钥
→ entrypoint 不写 /app/.env,不阻塞等待 MySQL/Redis
浏览器步骤 3 init-db
→ 写 /app/.env、config.json、settings、.install_state.json
步骤 4 create-admin
→ 写 admins,自动 lock(.install_locked)
entrypoint EXIT trap
→ /app/.env 复制到 nexus-state
重要:仅删除 1Panel 里的 MySQL 库 不会 清除 /app/.env;向导会提示「系统已初始化,无法重复执行数据库安装」。重装需删卷内 .env 并设 NEXUS_INSTALL_WIZARD_PENDING=1(见 §7.6)。
3. 安装向导(5 步)
3.1 流程与 API
| 步 | UI | API | 说明 |
|---|---|---|---|
| 1 | 欢迎 | — | 准备项 |
| 2 | 环境检测 | GET /api/install/env-check |
TCP 探测 MySQL/Redis;返回 docker_defaults |
| 3 | 数据库配置 | POST /api/install/test-credentials |
必须先检测账号密码 |
| 3 | 初始化 | POST /api/install/init-db |
建表、三写、发 install_token;.env 已存在则 403 |
| 4 | 管理员 | GET /api/install/connection-check |
读 .env 验 MySQL+Redis |
| 4 | 创建 admin | POST /api/install/create-admin |
需 install_token |
| 5 | 完成 | POST /api/install/lock(兜底) |
写 .install_locked;Docker 模式展示 1Panel 守护清单 |
辅助:GET /status、GET /state(断点续装;白名单脱敏,不含 install_token/redis_pass,有 token 时仅 has_token: true)。
实现文件:server/api/install.py、web/app/install.html。
3.2 步骤 3 表单(1Panel 正确填法)
| 字段 | MySQL | Redis |
|---|---|---|
| 主机 | 1Panel-mysql-xxxx |
1Panel-redis-xxxx |
| 端口 | 3306 |
6379 |
| 库名 | nexus |
库号 0 |
| 用户名 | nexus |
无(1Panel Redis 无账号;向导仅填密码) |
| 密码 | 1Panel「数据库」里建的 nexus 密码 | 1Panel Redis 应用参数中的口令 |
3.3 进程守护(1Panel Docker)
| 层级 | 机制 | 说明 |
|---|---|---|
| Layer 1 | Compose restart: unless-stopped + healthcheck |
容器崩溃自动拉起 |
| Layer 2 | Python self_monitor(30s) |
向导完成后正常模式自动运行 |
| Layer 3 | 宿主机 OpenResty + 可选 health_monitor.sh |
反代 127.0.0.1:8600;见 deploy/1panel/openresty-nexus.conf.example |
init-db 在 NEXUS_DOCKER_WRITE_ENV=1 时调用 _configure_docker_guardian(不在容器内写 Supervisor)。
3.4 Docker 预填来源
优先级(_onepanel_service_host):
- 环境变量
NEXUS_1PANEL_DB_HOST/NEXUS_1PANEL_REDIS_HOST /app/web/data/1panel-hosts.json(nx update写入卷)- 回退
host.docker.internal(1Panel 场景错误)
env-check 在 NEXUS_DOCKER_WRITE_ENV=1 时返回 docker_defaults(主机/端口/库名,不含 Redis 用户名)。前端会覆盖 stale 的 127.0.0.1 / host.docker.internal,并隐藏 Redis 用户名字段。
3.5 连接 URL 格式(必读)
MySQL(写入 NEXUS_DATABASE_URL):
mysql+aiomysql://nexus:密码@1Panel-mysql-xxxx:3306/nexus
Redis(写入 NEXUS_REDIS_URL)— server/api/install.py _build_redis_url:
| 场景 | URL 格式 |
|---|---|
| 1Panel(常见,推荐) | redis://:密码@1Panel-redis-xxxx:6379/0(向导用户名留空) |
| 1Panel ACL default | redis://default:密码@1Panel-redis-xxxx:6379/0 |
| 无密码 | redis://1Panel-redis-xxxx:6379/0 |
历史 bug(807f4c2 前):生成 redis://密码@host 会把密码当成用户名,导致 invalid username-password pair or user is disabled。升级后须 git pull + sync-install-wizard-to-container.sh。
4. 1Panel 部署流程
4.1 前置
- 安装 1Panel + Docker
- 应用商店安装 MySQL、Redis(自动创建
1panel-network) - 1Panel「数据库」:库
nexus、用户nexus(仅授权nexus库) - 记录 Redis 应用参数中的 连接口令(不是 MySQL 式账号)
4.2 安装 Nexus
# 新机(curl)
curl -fsSL "http://66.154.115.8:3000/admin/Nexus/raw/branch/main/deploy/quick-install.sh" | bash
# 或已有仓库
cd /opt/nexus && bash deploy/install-nexus-fresh.sh --skip-clone
完成后:https://<域名>/app/install.html
4.3 nx update 自动 sync(2026-06-06 根治版)
deploy/nexus-1panel.sh 在 install/upgrade 时:
detect-1panel-services.sh探测容器名- 写入
docker/.env.prod:NEXUS_1PANEL_*_HOST;NEXUS_REDIS_URL优先保留卷/向导中的redis://:pass@host(不经 Compose 注入容器) write_1panel_hosts_volume→1panel-hosts.json- 若存在
1panel-network,叠加docker-compose.1panel.yml(仅 networks,无重复 environment) - 已锁定:
sync_env_prod_to_volume将docker/.env.prod三密钥 +NEXUS_REDIS_URL/NEXUS_DATABASE_URL双写至nexus-state卷 - 已锁定:
set_install_complete将NEXUS_INSTALL_WIZARD_PENDING=0回写docker/.env.prod
4.4 OpenResty
- 1Panel → 网站 → 反代
http://127.0.0.1:8600 - HTTPS Let's Encrypt
- 参考:
deploy/1panel/openresty-nexus.conf.example(/ws/超时 ≥ 3600s) - 禁止脚本修改
/opt/1panel/apps/openresty/
4.5 资源档位
| Profile | 说明 |
|---|---|
1c4g |
小机 |
2c8g |
默认 |
4c16g |
--profile 4c16g |
持久化:docker/.host-profile。
5. 日常运维:nx 与 update
| 命令 | 等价 |
|---|---|
nx |
交互菜单 |
nx update |
deploy/update.sh → nexus-1panel.sh upgrade |
nexus-update |
同上 |
upgrade 顺序(2026-06-06+):
git fetch → MySQL 备份(失败默认 WARN)→ git reset --hard
→ sync_1panel_service_hosts → sync_env_prod_to_volume
→ tag 当前镜像为 nexus-prod-nexus:rollback
→ compose build → 镜像门控 (import server.main)
→ compose up -d --no-build
→(仅 install.html 非 200 时)sync-install-wizard-to-container.sh
→ set_install_complete → verify_health(端口 NEXUS_PUBLISH_PORT)
→ 健康失败:自动 tag rollback + up -d 回滚
| 参数 | 含义 |
|---|---|
--check |
仅查 Git |
--no-cache |
无缓存重建镜像 |
--no-backup |
跳过 mysqldump |
--require-backup |
mysqldump 失败则中止升级 |
--prune |
清理悬空镜像 |
推荐更新方式:cd /opt/nexus && bash deploy/update.sh(curl \| bash 会回退 /opt/nexus 并打印警告)。
5.1 密钥 / Redis URL 轮换(双写)
已锁定生产环境运行时以 卷内 /var/lib/nexus/.env 为准。轮换步骤:
- 修改宿主机
docker/.env.prod中NEXUS_SECRET_KEY/NEXUS_API_KEY/NEXUS_ENCRYPTION_KEY或NEXUS_REDIS_URL - 执行
sudo nx update— 脚本sync_env_prod_to_volume会同步至卷 - 验收:
docker exec <nexus> redis-cli -u "$URL" ping→PONG;/health→ok
Redis 容器改名时,resolve_nexus_redis_url 会尝试将旧 URL 中的密码迁移到新 host。
6. 脚本速查
| 脚本 | 用途 |
|---|---|
| deploy/README-1panel.md | 速查表 |
verify-1panel-install-wizard.sh |
服务器一键验收 |
detect-1panel-services.sh |
输出 NEXUS_1PANEL_*_HOST |
fix-1panel-mysql-grant.sh |
修复 MySQL 1045(nexus@'%') |
test-1panel-redis.sh |
Redis 多格式认证诊断 |
sync-install-wizard-to-container.sh |
热同步 install.html + install.py |
uninstall-mysql-compose.sh |
清理旧内置 MySQL 栈 |
7. 故障排查决策树
7.1 Redis 认证失败
症状:invalid username-password pair / NOAUTH / wrongpass
1. 主机是否为 1Panel-redis-xxxx?(不是 127.0.0.1)
2. 是否误把口令当成「root 用户名」?(1Panel Redis **无账号**,只填密码)
3. 密码是否与 1Panel → Redis → 参数 一致?
4. 运行 `bash deploy/test-1panel-redis.sh` 看哪种 URL 可用
5. 运行诊断:
cd /opt/nexus && bash deploy/test-1panel-redis.sh
在 Redis 容器内验证:
REDIS=$(docker ps --format '{{.Names}}' | grep -i '1Panel-redis' | head -1)
docker exec -it "$REDIS" redis-cli -u "redis://:你的密码@127.0.0.1:6379" ping
# 期望 PONG
查真实配置(密码与 ACL):
ls /opt/1panel/apps/redis/
grep -E 'requirepass|user ' /opt/1panel/apps/redis/*/conf/redis.conf 2>/dev/null
修正已有 .env(步骤 3 已执行过):
NEXUS=$(docker ps --format '{{.Names}}' | grep nexus-prod-nexus | head -1)
REDIS=$(grep '^NEXUS_1PANEL_REDIS_HOST=' /opt/nexus/docker/.env.prod | cut -d= -f2)
docker exec "$NEXUS" sed -i "s|^NEXUS_REDIS_URL=.*|NEXUS_REDIS_URL=\"redis://:你的密码@${REDIS}:6379/0\"|" /app/.env
docker restart "$NEXUS"
# 向导步骤 4 → 重新检测连接
7.2 MySQL 1045
症状:Access denied for user 'nexus'@'172.18.x.x'
- TCP 已通,但用户仅
nexus@localhost - 修复:
bash deploy/fix-1panel-mysql-grant.sh(需 1Panel MySQL root 密码,非 nexus 用户)
7.3 host.docker.internal
症状:Can't connect to MySQL/Redis on 'host.docker.internal'
cd /opt/nexus
bash deploy/detect-1panel-services.sh
nx update --no-cache
bash deploy/verify-1panel-install-wizard.sh
7.4 系统已初始化,无法重复执行数据库安装
/app/.env已存在,不要再点步骤 3 初始化- 若 Redis 错:改
.env中NEXUS_REDIS_URL(§7.1)→ 步骤 4 重检 - 若需完全重装:
NEXUS=$(docker ps --format '{{.Names}}' | grep nexus-prod-nexus | head -1)
docker exec "$NEXUS" rm -f /app/.env /app/.install_state.json /app/.install_locked
docker run --rm -v nexus-prod_nexus-state:/data alpine:3.19 rm -f /data/.env
# 确认 docker/.env.prod 中 NEXUS_INSTALL_WIZARD_PENDING=1
nx update --no-cache
7.5 外网 HTTPS 失败、本机 8600 正常
- 配置 OpenResty 反代 + SSL
curl -s http://127.0.0.1:8600/health→okcurl -sk https://域名/health→ 应ok
7.6 install.html 非 200
bash deploy/sync-install-wizard-to-container.sh
# 或 nx update --no-cache
8. 验收清单
cd /opt/nexus && bash deploy/verify-1panel-install-wizard.sh
关键 [PASS]:
- Git ≥
b25d079(1Panel sync) NEXUS_1PANEL_DB_HOST/NEXUS_1PANEL_REDIS_HOST- Nexus 在
1panel-network /app/.env不存在(安装模式)或连接检测全绿env-check的docker_defaults.db_host为1Panel-mysql-*
浏览器:步骤 3 先检测 → 初始化 → 步骤 4 创建 admin → /app/ 登录。
9. 提交修复索引
| 提交 | 主题 |
|---|---|
b25d079 |
nx update sync 1Panel 容器名;upgrade 补 sync_1panel_service_hosts |
d0544c9 |
fix-1panel-mysql-grant.sh;MySQL 1045 友好错误 |
da061d3 |
步骤 3 test-credentials 门禁 |
807f4c2 |
Redis URL redis://:pass@ 修复(曾误加 root,已废弃) |
3b2856f+ |
自动解析 :pass@ / default;步骤 4 connection-check 可自愈 .env |
10. 与功能开发 SSOT 的差异
| 点 | nexus-functional-development-guide.md §16 |
1Panel 实装 |
|---|---|---|
| 步骤 2/3 | 与 init-db 合并描述 | 步骤 2 仅 env-check;步骤 3 含 test-credentials |
| 配置三写 | 提及 config.php |
现为 config.json |
| 生产部署 §18 | Supervisor + 宝塔 | 以 nexus-1panel.sh / nx 为主 |
| Redis 主机 | 泛化为 localhost | 1Panel 必须容器名 + 仅密码(:pass@) |
11. 相关文档
- nexus-functional-development-guide.md — 全栈功能 SSOT
- nexus-functional-development-guide-appendix.md — API 附录
- production-verification-checklist.md — L5
- linux-dev-paths.md — 本地路径
- ../changelog/ — 按日变更记录
本文档随 1Panel 部署实践更新;代码行为以 server/api/install.py 与 deploy/nexus-1panel.sh 为准。