# docker-center
**Repository Path**: jinghui111/docker-center
## Basic Information
- **Project Name**: docker-center
- **Description**: 飞牛docker容器管理增强版 — 面向多应用用户的 Docker 管理与监控面板
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: main
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2026-10-26
- **Last Updated**: 2026-10-27
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# 飞牛docker容器管理增强版(docker-center)

👉 **想一次看完 7 张截图**:[Wiki · 界面截图](https://gitea.88531.cn/jinghui/docker-center/wiki/%E7%95%8C%E9%9D%A2%E6%88%AA%E5%9B%BE)
面向**多应用用户**的 Docker 管理与监控面板。核心不是「一堆容器」,而是把容器按 **应用(Compose 项目 / 单容器)** 聚合:一眼看哪个应用坏了、占用多少、怎么一键恢复。
> 所有截图都是在 **61 个容器真实运行** 的机器上直接截的(1440×900,无示意图),往下滚可看全部 7 张。

## 界面截图
| | |
|---|---|
| **单容器详情抽屉**:资源曲线 / 日志 / 配置 / 挂载网络四个 tab,一键停止·重启·暂停·删
 | **本地镜像**:占用、导出、批量启停删
 |
| **网络**:列表 + 新建网络
 | **备份与恢复**:面板数据 + Compose 配置打包下载
 |

## 它解决什么问题
Docker 自带面板和 Portainer 都是按「容器」管理:六十多个容器翻半天,一个应用里某个容器挂了根本看不出来。
本面板按**应用**(Compose 项目)聚合:一个应用 = 一组容器。打开就是「哪个应用坏了、吃多少资源、该优化什么」,坏的应用永远排在最前面。
## 功能一览
**概览(仪表盘)**
- 统计条:应用总数 / 异常 / 注意 / 资源占用 / 运行容器
- **性能趋势三图并列**:流量、CPU、内存;支持今天 / 昨天 / 近 30 天 / 近 12 个月,也能查任意一天(3 秒采样、按小时落盘,重启不丢)
- **四个 Top 5 榜并列**:CPU、内存、网络、运行时长,点任意一行进详情
- **优化建议**:10 类规则自动扫描(特权容器、挂 docker.sock、无内存上限、无健康检查、latest 镜像、悬空镜像、构建缓存、磁盘不足、反复重启、未纳入 Compose),可一键清理
- 需要关注的应用(只列异常/注意,最多 6 个)+ 最近事件时间线
**应用管理**
- 健康判定:部分容器未运行 → 红;健康检查失败 → 红;整体停止/资源超阈值 → 黄
- 每张卡片:CPU(占整机)、内存、网络、端口(点开直达)、**已运行时长**、24h 可用率、重启次数、问题摘要,卡片内直接启停重启
- 应用详情:全部容器表格 + 聚合日志(多容器合并)+ 事件,支持整应用启停
**容器与项目**
- 运行的容器:只列运行中,默认按**最新安装**排序,也可按 CPU/内存/网络/磁盘IO/进程数/名称排序,显示已运行时长
- 本地镜像(可清理悬空镜像)、镜像仓库拉取、**批量 Compose 部署**(多段用 `---` 分隔,可指定安装目录/项目名/ENV 参数)、网络
**备份与恢复**
- 一键备份面板数据(设置/事件/流量·CPU·内存历史)与 Compose 应用配置文件(不含数据卷),生成 tar.gz 可直接下载;附 `manifest.json`
**性能限制**
- 在容器抽屉或应用详情页给应用设 CPU(核)与内存(MB)上限,走 Docker cgroup 硬限制;应用级一次对全部容器生效,行内显示 `限 0.3核/96M` 角标;限制值持久化在 `data/limits.json`
**顶栏外链**
- 右上角、页面底部常驻横条、**每个页面内容末尾的推广卡片**三处都有「开源地址 / 导航站」入口,默认指向本机 Gitea 仓库与 BestNav;可在告警设置页改成自己的地址
**告警**
- CPU/内存阈值、Webhook 推送、同应用去重间隔、测试推送
## 和常见方案比
| 能力 | Portainer | Netdata / Beszel | 飞牛自带 | 本项目 |
|---|---|---|---|---|
| 按「应用」聚合管理 | ✗ | ✗ | ✗ | **✓** |
| 异常优先排序(打开就知道哪坏了) | ✗ | ✗ | ✗ | **✓** |
| 流量 / CPU / 内存 历史曲线(天·月·年 + 查某天) | ✗ | 有,但按容器 | ✗ | **✓ 按应用 + 整机** |
| 优化建议 + 一键清理空间 | ✗ | 仅告警 | ✗ | **✓ 10 类规则** |
| 一键启动「有镜像没起容器」的项目 | ✗ | ✗ | 部分 | **✓** |
| 资源占用 | ~50MB+ | 200MB+ / 需装 agent | — | **约 40MB,无 agent、无数据库** |
| 中文界面 | 部分 | ✗ | ✓ | **✓** |
## 优势
1. **按应用而不是容器** —— 多应用用户最痛的点,60 个容器变 50 个应用,一眼看清整体
2. **坏的应用永远排第一** —— 异常优先排序 + 菜单角标,不用再逐个点开找
3. **能直接省磁盘** —— 优化建议里悬空镜像、构建缓存可一键清理(本机实测约 55GB)
4. **趋势一眼可见** —— 三图并列 + 四榜并列,谁在偷偷吃 CPU/内存/带宽立刻现形
5. **够轻** —— 单容器约 40MB,无 agent、无 Prometheus、无数据库,数据以小时账本存本地 JSON
6. **零配置安装** —— 一条 `install.sh` 自动探测 docker 目录、生成配置、等待健康检查
7. **纯本地** —— 不依赖任何云服务,数据不出内网
> 安全提示:面板挂载 `/var/run/docker.sock`(等同宿主 root),**不要直接暴露公网**。
## 安装(新用户)
前置:Linux/飞牛 NAS 上已装 Docker 与 compose 插件(`docker compose version` 能跑)、有 `git`。
```bash
curl -fsSL https://gitee.com/jinghui111/docker-center/raw/main/install.sh | bash
```
脚本做的事:检查环境 → 自动探测 docker 目录 → 拉源码到安装目录 → 写 `.env` → `docker compose up -d --build` → 等健康检查通过 → 打印访问地址。
可覆盖参数(写在 `curl` 前面):
```bash
PORT=8080 \
COMPOSE_ROOT=/你的/docker目录 \
INSTALL_DIR=/opt/docker-center \
bash install.sh
```
| 变量 | 默认值 | 说明 |
|---|---|---|
| `PORT` | `7030` | 面板访问端口 |
| `COMPOSE_ROOT` | 自动探测(飞牛 `/vol1/1000/HD1/docker`,其次 `~/docker`) | 扫描 compose 文件、判断「未启动应用」的根目录 |
| `INSTALL_DIR` | `/vol1/1000/HD1/docker/docker-center` | 源码与数据目录 |
| `CONTAINER_NAME` | `docker-center` | 容器名 |
| `REPO_URL` | `https://gitee.com/jinghui111/docker-center` | 换源时用(内网可指向自建 Gitea) |
升级:再跑一次同一条命令即可(检测到已有仓库会 `fetch` + `reset --hard` 后重建)。
卸载:`cd <安装目录> && docker compose down -v && cd .. && rm -rf <安装目录>`。
### 用预构建镜像安装(不编译源码)
镜像已发布到公开仓库,**无需登录直接拉取**(两个地址内容完全一致,digest `sha256:37022ce4...`):
```bash
# 腾讯云 TCR(东京节点,海外/国内都稳,推荐)
docker pull jpccr.ccs.tencentyun.com/jinghui/docker-center:1.0.1
# 自建 Gitea(国内备用)
docker pull gitea.88531.cn/jinghui/docker-center:1.0.1
```
```yaml
services:
docker-center:
image: jpccr.ccs.tencentyun.com/jinghui/docker-center:1.0.1
container_name: docker-center
ports: ["7030:7030"]
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /:/host:ro
- ./data:/app/data
environment:
- TZ=Asia/Shanghai
restart: always
```
用到外部仓库时,把 `image` 换成对应地址即可。完整发布/推送流程(阿里云 ACR、腾讯云 TCR、Docker Hub、自建 Gitea、多架构)见 **[docs/publish-image.md](docs/publish-image.md)**:
```bash
docker login -u <用户名>
NAMESPACE=<命名空间> ./scripts/push-image.sh aliyun 1.0.0 # 或 tencent / dockerhub / gitea-lan
```
> 安全提示:面板挂载了 `/var/run/docker.sock`(等同宿主 root),**不要直接暴露公网**,放在内网或前面套一层带鉴权的反代。
## 版本与公告
面板右上角常驻版本号。有新版本时变成 `v1.0.2 → v1.0.3` 的高亮样式,点开能看到更新说明和发布页;公告走同一个铃铛入口,未读有红点,重要公告会弹一次窗(看过不再弹)。
数据来自授权中心(本项目的自建实例)。**上报内容只有三项**:随机生成的机器码、当前版本号、运行平台(linux/amd64 之类),不含容器名、镜像名、日志或任何业务数据。
不想上报就加一个环境变量 `HUB_DISABLED=1`(或在 `data/settings.json` 里把 `telemetry` 设为 `false`),关掉后不再上报,只保留公告拉取;授权中心挂掉时面板功能完全不受影响(失败开放)。面板界面不展示机器码、安装编号这些内部信息。
如果要指向自己的授权中心,改这三个环境变量即可:
```yaml
environment:
- HUB_URL=https://auth.example.com
- HUB_API_KEY=ak_xxxxxxxx
- HUB_PROJECT_ID=7
```
## 为什么按「应用」而不是「容器」管
61 个容器里其实只有 50 个应用(app + db + redis 属于同一个项目)。按容器管要逐个点,按应用管只需看:
- 这个应用**整体**是否健康(部分容器挂了会标红,而不是淹没在列表里)
- 它总共吃多少 CPU/内存、占了哪些端口
- 一键启动/停止/重启**整个应用**
- 出问题时有一条事件、一份合并日志
## 页面
| 页面 | 内容 |
|---|---|
| 概览(默认) | 纯仪表盘:应用总数/异常/注意/资源/运行容器统计条、**性能趋势三图并列**(流量 / CPU / 内存,今天·昨天·近30天·近12个月 + 查某一天,按小时记账落盘)、**CPU 与内存占用 Top 5**、优化建议、**需要关注的应用**(仅异常/注意,最多 6 个,卡片可直接启停)、最近事件;右上「查看全部应用」进入完整列表 |
| 全部应用 | 完整应用卡片列表(50 个):筛选(全部·有问题·已停止·高占用)、排序、状态胶囊、CPU/内存/网络、端口、已运行时长、可用率、重启次数、卡片内启停与详情;顶部可返回概览 |
| 应用详情 | 应用级指标 + 全部容器表格(状态/健康/CPU/内存/网络/重启/运行时长/单容器操作)+ 三个标签页:容器、聚合日志(多容器合并、按容器名加前缀)、事件;顶部可整应用启停重启 |
| 运行的容器 | 只列运行中容器;**默认按最新安装排序**(可选 CPU/内存/网络/磁盘IO/进程数/名称,按页面记忆)、搜索;行内显示**安装时间**、启停/重启/删除/详情/打开端口;有限制的容器显示 `限 0.3核/96M` 角标 |
| (停止的容器) | 侧栏已隐藏该入口;页面代码保留,含「有镜像但未启动的应用」批量启动/删除与已停止容器批量删除 |
| 本地镜像 | 使用情况(运行中/已停止引用/未使用)、**单个/批量导出 tar.gz**(保留 tag)、**导入 tar/tar.gz**、**批量删除**(被占用自动跳过)、**批量启动运行**(弹窗设重启策略/网络/端口/环境变量)、清理悬空镜像 |
| 镜像仓库 | 拉取镜像(流式进度);**批量 Compose 部署**:`# 目录:` / `# 项目:` / `# ENV: KEY=VALUE` + `---` 分隔多项目,可加安装目录前缀 |
| 网络 | **新建**(驱动/子网/网关/内部)与删除;内置与被占用的网络不可删;列出名称/驱动/子网/网关/容器数 |
| 备份与恢复 | 备份面板数据 + Compose 配置为 tar.gz,可下载/删除,附 `manifest.json` |
| 告警设置 | CPU/内存阈值、推送间隔、Webhook、开关、测试推送、查看事件 |
顶栏工具条:搜索、排序字段、升/降序切换、**刷新间隔(1/2/3/5/10/30 秒,默认 3 秒,存浏览器本地)**、**暂停/继续自动刷新**、手动刷新、添加容器。后端采样固定 3 秒,所以设成 1~2 秒只是更勤地读缓存,不会更快拿到新数据。
自动刷新是「无感」的:输入框/下拉正在聚焦、容器详情抽屉打开、处于设置或备份页、或刚有鼠标键盘操作(5 秒内)时会跳过重绘,静默刷新还会保留滚动位置——不会把你填到一半的表单或打开的窗口刷没。
## 首页优化建议
首页统计条下面是一块**优化建议**:服务端根据当前真实状态(容器配置 + 实时占用 + Docker 磁盘)生成,按 高 / 中 / 低 排序,超过 4 条自动折叠。
| 级别 | 规则 |
|---|---|
| 高 | 特权容器(privileged);容器重启 ≥3 次;磁盘可用 <10% |
| 中 | 挂载 docker.sock;内存占用接近上限(>85%);单容器 CPU >60%;容器未设内存上限且合计 >1GB;悬空镜像 >1GB;构建缓存 >5GB;应用整体已停止 |
| 低 | 对外容器没有 HEALTHCHECK;使用 latest 镜像;单容器应用未纳入 Compose |
- 同类问题会**合并成一条**(例如「31 个应用使用 latest 镜像,涉及 …」),不会一个应用刷一条。
- 可一键处理的直接给按钮:**清理悬空镜像**、**清理构建缓存**(都不影响运行中的容器)、**启动已停止应用**;其余给「查看」跳到应用详情自己改 compose。
- 建议每次刷新(3 秒)重新计算,但 Docker 磁盘统计缓存 60 秒,避免频繁扫描镜像层。
## 健康判定规则
| 级别 | 触发条件 |
|---|---|
| 异常(红) | 应用里**部分容器未运行**(其余在跑);任一容器健康检查 `unhealthy` |
| 注意(黄) | 应用整体已停止;健康检查 `starting`;CPU 占整机超阈值;容器内存占上限超阈值;容器重启次数增加(单独一条事件) |
| 正常(绿) | 以上都不满足 |
- 状态从正常→异常/注意、异常→恢复都会写一条事件;「一上线就异常」的应用首次发现也会补记一条。
- 可用率:每分钟记录一次应用是否正常,保留 24 小时,卡片显示窗口内可用率。
- 事件保留最近 400 条(内存),重启服务后清空。
## 告警推送(Webhook)
在「告警设置」填 Webhook 地址,收到的是 POST JSON:
```json
{
"title": "[异常] my-app",
"level": "critical",
"app": "my-app",
"detail": "1 个容器未运行(my-app-db)",
"time": "2026/10/26 16:43:46",
"host": "gzFNos2"
}
```
注意两点:
1. **容器内的 `127.0.0.1` 是容器自己**,要推给宿主机上的服务请用宿主 LAN IP(如 `http://192.168.68.19:端口/hook`)或 `http://host.docker.internal:端口/hook`(compose 已加 `host-gateway`)。
2. 同一应用在 `debounceMinutes`(默认 10 分钟)内只推一条,避免刷屏。
## 运维
默认部署:端口 `7030`,`restart: always`,内存上限 384MB(实测常驻约 40MB),源码目录 `/vol1/1000/HD1/docker/docker-center`。
```bash
cd /vol1/1000/HD1/docker/docker-center
docker compose up -d --build # 改动后重建
docker compose logs -f # 看日志
docker compose restart # 重启
```
- 配置持久化:`data/settings.json`(阈值、webhook、开关)
- 环境变量:`PORT`、`SAMPLE_MS`(3000)、`INSPECT_MS`(15000)、`DISK_PATH`、`SETTINGS_PATH`
## 实现要点 / 坑
- 采样:每 3 秒并行拉一次所有运行中容器的 `stats`;CPU% 用 `cpu_stats`/`precpu_stats` 差值 × 核数;内存扣 `inactive_file`;网络与块设备速率靠相邻采样差分。
- 重启次数/健康状态来自 `inspect`,每 15 秒才刷一遍(每 3 秒 inspect 61 个容器太重)。
- 日志是 Docker 的 8 字节头多路复用流,用 `demuxLogs` 手动解帧;`modem.demuxStream` 在 follow=false 时会挂住请求。
- 排序比较器统一按「降序」写,`order=asc` 时取反,否则会出现 desc 变升序。
- 详情页是独立视图状态(`app-detail`),轮询刷新时必须保住它,否则每 4 秒会被看板覆盖。
## 已知限制
- 曲线与可用率都在内存里,重启服务后重新累积(可用率保留 24 小时窗口)。
- 不提供在线改容器配置,改配置请用 Compose 或重建容器。
- 应用归属依赖 `com.docker.compose.project` 标签;手工 `docker run` 的容器各自算一个「单容器应用」。