DockerView-Go:用 Go 写一个终端 Docker 监控工具,顺便做了个 Web 仪表盘


前言

平时开发基本离不开 Docker,线上服务需要监控许多容器状态,但用 docker stats 看容器状态总觉得不太舒服——界面简陋、信息密度低,切个窗口还麻烦。Portainer 倒是功能全,但跑一个容器监控要起一整套服务,杀鸡用牛刀。

于是就想自己写一个。目标很简单:一个二进制文件,终端里跑起来就能用,最好还能有个 Web 界面方便远程看

DockerView-Go 就是这么来的,至于为什么要带 go 因为我之前基于 python 设计过一个 dockerview 项目,后来性能问题,于是用 golang 重构了。

架构

项目的核心思路是双模式共享数据源

┌─────────────────────────────────────────────┐
│              cmd/dockerview/main.go          │
│         CLI flags, goroutine orchestrator    │
├──────────────┬──────────────────────────────┤
│  TUI Mode    │      Server Mode             │
│  (bubbletea) │  (HTTP + SSE + Embedded SPA) │
├──────────────┴──────────────────────────────┤
│         internal/docker/client.go           │
│      Docker SDK wrapper, stats parser       │
└─────────────────────────────────────────────┘

终端模式和 Web 模式用的是同一套数据——一个每秒轮询 Docker API 的 goroutine。数据通过 sync.Mutex 在 TUI 和 Server 之间共享,互不干扰。

终端模式基于 bubbletea + lipgloss,零依赖,敲 dockerview 直接跑。Web 模式加个 -server 参数就行,HTTP 服务器通过 SSE 实时推送数据,前端是 React SPA,通过 embed.FS 嵌入到二进制里,分发时只需一个文件。

几个有意思的设计

Docker Socket 自动检测

很多 Docker 工具只认 /var/run/docker.sock,但我在 macOS 上用 Colima以及用 OrbStack 这些的人不少,Socket 路径完全不一样。

现在启动时会按优先级依次尝试:DOCKER_HOST 环境变量 → 标准 Socket → Colima/OrbStack/Podman/Rancher Desktop 的路径。每个都跑一遍 Ping() 验证,能连上就用。

sockets := []string{
    "/var/run/docker.sock",
    home + "/.colima/default/docker.sock",
    home + "/.orbstack/run/docker.sock",
    // ...
}

实测下来基本覆盖了主流的 Docker 运行时,开箱即用。

容器健康度评分

这个功能是后来加的,初衷是"光看 CPU 和内存数字不够直观"。于是设计了一套 0-100 的评分系统,六个维度加权:

维度权重逻辑
CPU20%<50% 满分,50-80% 线性衰减,>80% 急剧下降
内存20%同上
磁盘 I/O15%<50 MB/s 满分,>200 MB/s 扣分
网络15%过低或过高都扣(太低可能是容器卡住了)
重启次数15%每次重启扣 5 分
运行时间15%>1小时满分,<1分钟低分

最终映射为三个状态:healthywarningdangerous,在 Web 仪表盘顶部面板分组展示,一眼就能看出哪些容器有问题。

SSE 推送 + 慢客户端处理

Web 端用 SSE 做实时数据推送,比 WebSocket 轻量很多。每个连接对应一个带缓冲的 channel(容量 5),发送时走非阻塞 select

for _, clientChan := range clients {
    select {
    case clientChan <- data:
    default:
        // 慢客户端跳过这一帧
    }
}

如果某个客户端处理不过来,就直接跳过,不会阻塞其他客户端。实测多标签页同时打开也很流畅。

Token 安全

Web 模式支持访客只读 + 管理员认证双层安全。未指定 Token 时自动生成 16 字节随机密钥,支持 URL 参数、Header、Bearer Token 三种传递方式。启停容器、查看日志、执行命令这些写操作都需要认证。

嵌入式前端

前端用 React + TypeScript + Vite 构建,通过 Go 的 embed.FS 直接嵌入:

//go:embed all:web
var webContent embed.FS

一个文件搞定,不用额外部署静态资源。前端做了玻璃拟态风格的 UI、SVG 迷你图趋势、深色/浅色主题切换、中英文双语。

功能清单

  • 终端 TUI:键盘快捷键操控容器
  • Web 仪表盘:实时数据卡片 + SVG 历史趋势 + 健康度面板
  • 日志查看器:关键字搜索、等级过滤、搜索高亮
  • 命令执行:Web 端直接在容器里跑 Shell,内置快捷模板
  • 端口映射可视化:一键跳转到容器服务
  • 一键更新:Web 端触发 GitHub Release 自动升级
  • 跨平台:macOS / Linux / Windows(amd64 + arm64)

快速上手

安装

# go install (golang环境推荐)
go install github.com/zsuroy/dockerview-go/cmd/dockerview@latest

或直接下载编译好: https://github.com/zsuroy/dockerview-go/releases

使用

# 终端模式
dockerview

# 启动 Web 仪表盘
dockerview -server

# 启动 web 仪表盘并配置自定义密码
dockerview -server -token password

技术栈

技术
终端 TUIGo + bubbletea + lipgloss
Web 后端Go net/http + SSE
Web 前端React + TypeScript + Vite + Tailwind CSS v4
Docker 交互docker/client SDK
UI 组件Radix UI

尾声

这个项目从最初的"看看容器 CPU 多少了"演变成了一个功能还挺全的监控工具。过程中遇到不少有意思的问题——SSE 并发推送的性能调优、Docker Socket 多环境适配、embed.FS 嵌入前端的构建流程等等,之后有机会再单独写。

项目完全开源,有问题欢迎交流:

声明:Grows towards sunlight |版权所有,违者必究|如未注明,均为原创|本网站采用BY-NC-SA协议进行授权

转载:转载请注明原文链接 - DockerView-Go:用 Go 写一个终端 Docker 监控工具,顺便做了个 Web 仪表盘


Grows towards sunlight and Carpe Diem