Repository navigation
Releases: Bet5521/onecloud-panel
Release list
v2.2.12
feat: 新增 Docker 管理页面,按节点管理容器与镜像
背景:此前只有「应用管理」(面板配方安装、有安装记录)和「节点详情 → Docker 引擎」
(服务级安装/启停)。节点上手工 docker run 出来的容器既不在应用列表里,
也没有统一的操作入口,只能上机敲命令。
新增「Docker 管理」页面(菜单项,权限 node:read):
- 容器:启动 / 停止 / 重启 / 删除 / 查看尾部日志(可选 100~1000 行);
状态、镜像、端口、创建时间、可写层大小一屏可见;
「面板安装」标签标出有面板安装记录的容器(建议到应用详情操作,
避免手工 stop 后与面板记录不一致)。 - 镜像:按节点列出仓库:标签、ID、大小、创建时间、在用容器数,可删除未被占用的镜像。
- 拉取镜像:后台任务(docker_pull_image),带进度输出。
- 清理:只做两类安全清理——已停止的容器、悬空(无 tag)镜像;
不删带 tag 的镜像与未使用的卷/网络。 - 节点选择器支持「全部节点(聚合)」:并发查询各节点,
单个节点失败不影响其它节点,失败原因随该节点一行回传(聚合视图只列容器,
镜像/拉取/清理按节点操作)。
后端:
- 新增 internal/apps/docker_manage.go:容器/镜像列表解析、容器操作、日志、
镜像删除、拉取、清理,以及多节点聚合。 - 新增任务类型 docker_pull_image / docker_prune,终态写审计。
- 新增接口:
GET /api/nodes/{id}/docker/containers
POST /api/nodes/{id}/docker/containers/{cid}/action
GET /api/nodes/{id}/docker/containers/{cid}/logs?tail=N
GET /api/nodes/{id}/docker/images
DELETE /api/nodes/{id}/docker/images/{iid}
POST /api/nodes/{id}/docker/images/pull
POST /api/nodes/{id}/docker/prune
GET /api/docker/containers(聚合)
读操作需 node:read,写操作需 node:write 并写审计。 - Agent 的 Docker 代理白名单补上 POST /images/prune(面板只用 dangling=true
删悬空镜像,全量 prune 不放行)。
细节与防错:
- 容器/镜像 ID 走白名单正则再拼进 Engine API 路径,挡住路径穿越。
- 端口优先显示宿主端口并去重;无映射时退回容器端口,避免端口列全空。
- 连不上 Engine 时区分「未安装」与「装了没启动」,给出对应指引,
而不是统一报dial unix /var/run/docker.sock。 - 删除运行中的容器自动带 force=true(先 SIGKILL 再移除),并在确认框里说明。
验证:
- 新增 apps 用例:容器列表解析/排序/端口去重与回退/sha256 前缀截断、
面板安装标记、路径穿越拒绝、Engine 非 200 报错、聚合视图容错、
镜像 解析、未知清理目标拒绝。 - 新增 api 用例:聚合路由与鉴权、未知容器操作/清理目标 400。
注意 CI(ubuntu runner)自带 Docker,故不写「某节点必然连不上」这类环境断言。 - go build / go vet 通过;go test ./... -p 1 全量通过(20 个包)。
- 前端 vite build 通过;运行时冒烟:聚合 200 空列表、单节点返回中文指引、
未知操作/清理目标 400。
完整提交:f2051ca
v2.2.11
feat: xiaomusic 增加直装、节点 Docker 生命周期管理、外部应用监控
一、xiaomusic 增加直装方式(原仅有 Docker)
- 改为 methods: [native, docker],直装优先。
- 直装走官方 PyPI 包:python3-venv 建独立虚拟环境 → pip 安装 xiaomusic==<版本>,
专用系统账号 xiaomusic 运行(与 gitea 一致:先建组再建用户,避免
USERGROUPS_ENAB=no 时 systemd 的 Group= 找不到组)。 - 环境变量显式给绝对路径(music/conf/cache/tmp/download),避免相对路径被解释
成 WorkingDirectory 下的目录。 - Python 版本前置检查:项目要求 >= 3.10,Debian 11 自带 3.9,直接给出
「改用容器方式或升级系统」的明确提示,而不是让 pip 抛一堆解析错误。 - armv7 上 pillow/pycryptodome 常无预编译包:首次安装失败会自动补装
build-essential/python3-dev/图形库后重试,并额外启用 piwheels 索引。
二、节点 Docker 生命周期管理(安装 / 启动 / 停止 / 重启 / 卸载)
- 新增 internal/apps/docker_lifecycle.go + 任务类型 docker_lifecycle。
- 状态判定不再只看 Engine ping:ping 失败后再看「装没装 / 单元是不是 active」,
区分 运行中 / 已安装未运行 / 未安装 —— 这三种状态在界面上该给不同按钮。 - 卸载先 disable 服务再 purge 软件包并清理 APT 源;默认保留 /var/lib/docker,
只有显式 purge_data 才删除镜像与容器数据。 - 任务终态写审计(docker_start/stop/restart/uninstall),面板重启后按节点实际
状态对账。
三、节点已安装应用监控(支持非面板安装的应用)
- 新增 external_apps 表(迁移 022)与 CRUD API:
GET/POST /api/nodes/{id}/external-apps、
PUT/DELETE /api/nodes/{id}/external-apps/{eid}、
POST /api/nodes/{id}/external-apps/{eid}/action。 - 三种监控方式:
systemd 单元(systemctl show 的 ActiveState/SubState)、
进程匹配(pgrep -f,取前 5 个 PID)、
容器名(Engine API /containers//json)。 - 展示状态、PID、CPU/内存占用、运行时长、命令行,端口可选(ss/netstat 探测监听)。
- 启停:systemd 走 systemctl;进程走 pkill -TERM 与登记的启动命令
(setsid nohup 脱离会话,日志落 /var/log/ocp-external-.log);容器走 Engine API。 - 安全:单元名走白名单正则,容器名禁空格/斜杠,端口范围校验;所有写操作
需 node:write 权限并写审计。节点删除时一并清理其登记项。
四、前端(节点详情)
- 新增「Docker 引擎」卡片:状态标签 + 版本 + 安装/启动/停止/重启/卸载按钮,
卸载用输入 purge 二次确认,避免误删镜像与容器。 - 新增「外部应用监控」卡片:表格展示类型/目标/状态/资源/端口与启停删改按钮,
另有登记/编辑对话框(按类型切换目标提示与启动命令输入)。
验证:
- 配方:TestBuiltinRecipesLoadAndRender / TestBuiltinNativeRecipesPrepare 通过
(含模板渲染与变量校验)。 - 新增 apps 用例:登记项校验(systemd 注入、容器名、端口、未知类型)、
systemd/进程探测输出解析、多 PID 与端口监听、ProbeExternals 顺序与状态、
删除节点清理登记项。 - 新增 api 用例:外部应用 CRUD 与鉴权、跨节点访问 404、未知 Docker 操作 400。
- go build / go vet 通过;go test ./... -p 1 全量通过(20 个包)。
- 前端 vite build 通过;运行时冒烟:面板初始化 → 登记外部应用 → 列表返回
实时状态(JSON 字段为小写,与前端一致)→ Docker 状态返回 absent,均 200。
完整提交:06ff886
v2.2.10
fix: 修复面板与 Agent 的 HTTP 连接泄漏(内存/goroutine/fd 持续增长)
现象:面板进程与节点 Agent 的内存随时间持续上涨,久跑后 fd 耗尽、响应变慢。
根因(同一个错误模式,三处):
-
internal/docker/engine.go 的 NewLocalClient 每次调用都新建一个
http.Transport,而 Transport 会为每条空闲连接常驻 readLoop/writeLoop 两个
goroutine;goroutine 是 GC 根并反向引用 Transport,于是「用完就丢」的
Transport 永远不会被回收——连接不关、goroutine 不退、收发缓冲区不释放。
零值 Transport 的 IdleConnTimeout 还是 0,连空闲超时兜底都没有。
触发点:- 面板每 30s 的本机节点刷新(EnsureLocalNode → DetectLocal)
- 面板每 30s 的应用状态探测(AppStatesByNode → EngineFor,每个节点各一个)
- 面板每次 Docker 状态/日志/安装操作(EngineFor)
- Agent 每次 Docker 代理请求(/v1/docker/*)
- Agent 每 30s 一次心跳(Heartbeat → DetectLocal)
-
internal/agent/client.go 的 doJSON 在配置了证书指纹固定(pin)或
OCP_INSECURE_TLS 时,每次心跳都新建一个带自定义 TLS 的 Transport,
同样永不回收(还额外挂着 TLS 缓冲区)。实测(50 轮探测):旧实现 goroutine 3 → 153(+150,每次 +3);
改为共享客户端后 156 → 162(+6,纯噪声)。
修复:
- docker 包新增 LocalHTTPClient(socket):按 socket 复用的进程内单例客户端,
并显式设置 MaxIdleConns/MaxIdleConnsPerHost=16、IdleConnTimeout=90s;
NewLocal 改走共享池;NewLocalClient 保留原语义(独立客户端)并补注释要求
调用方 CloseIdleConnections。EngineFor 与 docker 代理改用共享客户端。 - Agent 的 doJSON 改为按 (insecure, pin) 缓存客户端;无 pin/insecure 时直接
复用 net/http 的共享 Transport。另注意:值为 nil 的 *http.Transport 赋给
接口字段会得到「非 nil 接口」,Client 会拿它发请求并 panic,故默认分支保持
Transport 零值。 - 前端:NodesView 卸载时兜底 teardownTerm()。此前只有对话框 @close 会释放,
切路由/组件销毁时 WebSocket 保持打开,服务端那条 SSH 会话与其收发 goroutine
一直挂着,前端 xterm 实例与 ResizeObserver 也留在内存里。
验证:
- 新增 internal/docker 回归用例:同一 socket 必须返回同一客户端实例、
Transport 必须设置 IdleConnTimeout 与连接数上界、用真实 unix socket 连续
探测 100 轮后 goroutine 不得线性增长(修复前每轮 +3)。 - 新增 internal/agent 用例:默认/pin/insecure 三种配置各自缓存,pin 归一化
(去前缀、小写)命中同一实例,不同 pin 互不共用。 - go build / go vet 通过;go test ./... -p 1 全量通过(20 个包);
前端 vite build 通过;面板启动冒烟正常(入口与静态资源均 200)。
完整提交:af09f7e
v2.2.9
feat: 仪表盘历史指标趋势新增图表,并让发版说明展示变更摘要
一、历史指标趋势:右侧新增趋势图
原来只有一张按时间排列的采样清单,只能逐行核对数值,看不出走势。
现在拆成左右两栏:左栏保留原始采样清单,右栏新增趋势折线图。
- 新增零依赖 SVG 图表组件 web/src/components/MetricTrendChart.vue。
不引第三方图表库:前端会被打包进 Go 二进制、跑在 armv7 这类小设备上,
为一个趋势图拖进上百 KB 运行时不划算,而这里的需求(多序列、双 Y 轴、
悬停读数)用 SVG 直写完全可控,也没有主题/版本适配隐患。 - 双 Y 轴:CPU / 内存 / 磁盘是百分比,固定走左轴 0–100;
负载 1m 是绝对值(通常 0.x–2),单独走右轴,否则会被压在底部看不出变化。 - 交互:悬停显示竖向准星 + 该时刻全部指标读数;点击图例可隐藏/显示某条曲线
(不允许全部隐藏,全空图表比留一条线更让人困惑)。 - 新增时间范围选择(最近 6 / 12 / 24 小时),图表与清单联动。
- 采样密度处理:24h×30s 有 2880 点,直接进 DOM 没有意义,按上限抽稀渲染,
但保留原始数据下标,保证悬停读的是真实样本而不是抽稀后的近似值。 - 缺采样(null/非有限值)处曲线断开,而不是在两个真实点之间连出一条假直线。
纯计算部分抽到 web/src/chartScale.js,可脱离浏览器直接跑断言。
二、发版说明改为按改动内容生成的摘要
Release 的「更新说明」会被面板「设置 → 版本更新」原样展示给用户,
此前用的是 GitHub 自动生成(只列提交标题和 PR),用户看不到「改了什么、为什么改」。
现改为取本次提交的标题 + 正文作为 Release body。
验证:
- 图表计算断言(niceMax / downsample / axisLabel / buildSegments / hoverIndex)
全部通过;其中 buildSegments 修掉一个真实缺陷——越界值此前依赖调用方
传入的 yOf 做夹紧,已改为在生成坐标这一步就压回画布内。 - 前端 vite build 通过;运行时冒烟:面板可正常提供入口 JS 与图表 chunk(均 200)。
- go build / go vet 通过;go test ./... -p 1 全量通过(19 个包)。
- release.yml 经 YAML 解析校验,更新说明生成脚本本地演练通过。
完整提交:5a387d2
v2.2.8
v2.2.7
v2.2.6
v2.2.5
v2.2.4
Full Changelog: https://github.com/Bet5521/onecloud-panel/commits/v2.2.4