Docker Inspector 技术文档
版本:1.0.0 | 基于 Java 21 | 运行时依赖:JDK 21+
一、程序概述
Docker Inspector 是一款轻量级命令行工具,通过 Docker Engine REST API 远程采集目标 Docker 服务器的运行信息,包括:
- Docker 引擎版本信息(API 版本、引擎版本、Go 运行时版本、系统架构、内核版本)
- 容器列表与状态(所有容器的运行状态、镜像来源、端口映射、运行时长)
- 镜像仓库清单(本地所有镜像的标签、大小、创建时间)
程序以"采集 → 格式化输出 → 退出"的一次性模式运行,适用于运维巡检、环境快照、自动化脚本集成等场景。
二、实现原理
2.1 整体架构
┌─────────────────────┐ HTTP GET ┌──────────────────────┐
│ Docker Inspector │ ─────────────────────────▶ │ Docker Engine API │
│ (Java 21 CLI) │ ◀───────────────────────── │ 192.168.3.145:2375 │
└─────────────────────┘ JSON 响应 └──────────────────────┘
│
▼
┌─────────────────────┐
│ 解析 JSON → 格式化 │
│ 输出到标准输出流 │
└─────────────────────┘
程序的运行流程如下:
- 初始化 HTTP 客户端 --- 构建 Java 内置的
HttpClient实例,配置连接超时 - 依次调用三个 REST 端点 ---
/version、/containers/json?all=true、/images/json - 解析 JSON 响应 --- 使用 Jackson 将响应体解析为
JsonNode树结构 - 提取字段并格式化 --- 按固定宽度对齐输出到控制台
- 进程退出 --- 所有数据输出完成后,
main方法自然返回,JVM 退出
2.2 Docker Engine REST API
Docker 守护进程暴露的 HTTP API 是本程序的核心数据来源。当 Docker 以 -H tcp://0.0.0.0:2375 方式启动时,外部程序即可通过 HTTP 访问。
本程序使用了以下三个端点:
| 端点 | HTTP 方法 | 返回内容 |
|---|---|---|
/version |
GET | Docker 引擎版本、API 版本、Go 版本、系统架构 |
/containers/json?all=true |
GET | 所有容器(含已停止)的 ID、名称、镜像、状态、端口映射 |
/images/json |
GET | 本地所有镜像的 ID、标签、大小、创建时间 |
/version 响应示例
json
{
"ApiVersion": "1.49",
"Version": "28.1.1",
"GoVersion": "go1.23.8",
"Arch": "amd64",
"KernelVersion": "6.6.0-102.0.0.8.oe2509.x86_64"
}
/containers/json?all=true 响应示例
json
[
{
"Id": "9d4a2bb13848...",
"Names": ["/pascal-ming-iiot"],
"Image": "pascal-ming-iiot:6.0.0",
"State": "running",
"Status": "Up 11 minutes",
"Ports": [
{ "IP": "0.0.0.0", "PrivatePort": 39999, "PublicPort": 39999, "Type": "tcp" }
]
}
]
/images/json 响应示例
json
[
{
"Id": "sha256:9a50f2f8bc4c...",
"RepoTags": ["hirun-node-red:4.1.10-22"],
"Size": 981495831,
"Created": 1749050563
}
]
2.3 为什么选择直接调用 REST API 而非 docker-java SDK
| 维度 | 直接调 REST API(本方案) | docker-java SDK |
|---|---|---|
| 依赖体积 | 仅 Jackson(~1.8 MB) | SDK + Netty(~5-8 MB) |
| 版本兼容性 | Docker API 向后兼容,极少变动 | SDK 版本需与 Docker 版本对齐 |
| 学习成本 | HTTP + JSON,无额外概念 | 需学习 SDK 抽象层 |
| 可调试性 | curl 可直接复现请求 | 需通过 SDK 内部日志排查 |
| 适用场景 | 只读查询,端点有限 | 需要创建/删除容器等复杂操作 |
本程序仅做只读查询,三个端点已足够覆盖全部需求,直接调 REST API 是更轻量、更可控的选择。
三、关键技术组件
3.1 Java 21 HttpClient(java.net.http)
java
this.httpClient = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(10))
.build();
java.net.http.HttpClient 自 JDK 11 起成为标准 API,JDK 21 中已完全成熟。相比 Apache HttpClient 或 OkHttp,它零外部依赖、与 JDK 生命周期一致、支持 HTTP/2。
本程序使用同步发送模式:
java
HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
超时设计:连接超时 10 秒、请求超时 15 秒,保证在网络不可达时程序不会无限挂起。
3.2 Jackson JSON 处理
java
this.mapper = new ObjectMapper();
// 获取时解析
return mapper.readTree(response.body()); // 返回 JsonNode 树
// 安全读取字段
String apiVersion = version.path("ApiVersion").asText("N/A");
ObjectMapper.readTree() 将 JSON 字符串解析为树模型(JsonNode),通过 path() 方法安全导航------字段不存在时返回 MissingNode,调用 asText("N/A") 不会抛异常而是返回默认值,避免了大量的 null 检查。
3.3 Java 21 Switch 表达式(Pattern Matching)
java
String stateColor = switch (state) {
case "running" -> { running++; yield "🟢"; }
case "exited" -> { stopped++; yield "🔴"; }
default -> { stopped++; yield "🟡"; }
};
Java 21 的 switch 表达式支持箭头语法和代码块,允许在分支中执行副作用(running++)并用 yield 返回值,比传统的 switch-case-break 结构更紧凑、更不容易遗漏 break。
3.4 格式化输出
java
System.out.printf("║ 服务器地址 : %-35s ║%n", DOCKER_HOST + ":" + DOCKER_PORT);
%-35s 表示左对齐、占 35 字符宽度,配合 Unicode 制表符(╔═╗║╚)构建固定宽度的表格边框。
辅助方法:
truncate(s, max)--- 超长字符串截断并附加..,防止输出溢出formatSize(bytes)--- 字节自动换算为 KB/MB/GBformatTimestamp(unixSeconds)--- Unix 时间戳转本地时间格式
四、程序结构
4.1 文件布局
docker-java/
├── pom.xml # Maven 构建配置
├── docs/
│ └── README.md # 本文档
├── src/
│ └── main/
│ └── java/
│ └── com/
│ └── example/
│ └── DockerInspector.java # 主类,单文件约 200 行
└── target/
└── docker-inspector-1.0.0.jar # 打包产物(含全部依赖)
4.2 类结构(DockerInspector.java)
DockerInspector
├── 常量
│ ├── DOCKER_HOST / DOCKER_PORT / BASE_URL # 目标服务器地址
│
├── 成员
│ ├── HttpClient httpClient # HTTP 客户端(线程安全)
│ └── ObjectMapper mapper # JSON 解析器(线程安全)
│
├── 核心方法
│ ├── get(String path) → JsonNode # 通用 GET 请求封装
│ ├── printDockerVersion() # 输出引擎版本信息
│ ├── printContainers() # 输出容器列表与状态
│ └── printImages() # 输出镜像清单
│
├── 工具方法
│ ├── truncate(String, int) → String # 字符串截断
│ ├── formatSize(long) → String # 文件大小格式化
│ └── formatTimestamp(long) → String # 时间戳格式化
│
└── main(String[] args) # 入口,依次调用三个 print 方法
4.3 执行流程
main()
│
├── new DockerInspector()
│ ├── HttpClient.newBuilder().connectTimeout(10s).build()
│ └── new ObjectMapper()
│
├── printDockerVersion()
│ ├── GET /version
│ ├── mapper.readTree(body)
│ └── printf 输出表格
│
├── printContainers()
│ ├── GET /containers/json?all=true
│ ├── mapper.readTree(body)
│ ├── 遍历数组 → 提取 Id/Name/Image/State/Ports
│ ├── 统计 running / stopped 数量
│ └── printf 逐行输出
│
├── printImages()
│ ├── GET /images/json
│ ├── mapper.readTree(body)
│ ├── 遍历数组 → 提取 Id/RepoTags/Size/Created
│ └── printf 逐行输出
│
└── 输出 "信息收集完毕,程序退出。"
4.4 Maven 构建配置要点
xml
<!-- pom.xml 关键配置 -->
<properties>
<maven.compiler.source>21</maven.compiler.source> <!-- 编译目标 JDK 21 -->
<maven.compiler.target>21</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId> <!-- 唯一外部依赖 -->
</dependency>
</dependencies>
<plugins>
<plugin>
<artifactId>maven-shade-plugin</artifactId> <!-- 将依赖打入单一 jar -->
</plugin>
</plugins>
maven-shade-plugin 将 Jackson 的三个 jar(core / annotations / databind)合并进最终的 docker-inspector-1.0.0.jar,实现"一个 jar 走天下",目标机器只需有 JDK 21 即可直接运行。
五、运行方式
5.1 编译打包
bash
mvn clean package -q
产出物:target/docker-inspector-1.0.0.jar(含全部依赖,约 2.1 MB)
5.2 执行
bash
# Linux / macOS
java -jar target/docker-inspector-1.0.0.jar
# Windows(解决中文乱码)
java -Dfile.encoding=UTF-8 -Dstdout.encoding=UTF-8 -Dstderr.encoding=UTF-8 \
-jar target/docker-inspector-1.0.0.jar
5.3 Docker 服务器前置条件
目标 Docker 守护进程需开启 TCP 监听:
bash
# /etc/docker/daemon.json 或 dockerd 启动参数
{
"hosts": ["unix:///var/run/docker.sock", "tcp://0.0.0.0:2375"]
}
或在 systemd 服务文件中设置:
ini
# /etc/systemd/system/docker.service.d/override.conf
[Service]
ExecStart=
ExecStart=/usr/bin/dockerd -H fd:// -H tcp://0.0.0.0:2375
安全提示:2375 端口无认证,生产环境建议启用 TLS(2376 端口)并配置客户端证书。
六、扩展功能展望
6.1 命令行参数化
当前服务器地址硬编码在常量中,可改为命令行参数或配置文件驱动:
bash
# 目标形态
docker-inspector --host 192.168.3.145 --port 2375
docker-inspector --config servers.yml
技术方案:引入 picocli(零依赖、注解驱动的命令行解析框架)替代硬编码常量,支持 --host、--port、--output json 等参数。
6.2 多服务器批量巡检
支持同时连接多台 Docker 服务器,并发采集后汇总输出:
bash
docker-inspector --host 192.168.3.145,192.168.3.146,192.168.3.147 --port 2375
技术方案:使用 HttpClient + CompletableFuture 并发请求,或结构化并发(Java 21 StructuredTaskScope)等待全部完成后再格式化输出。
6.3 输出格式扩展
当前仅支持控制台文本输出,可扩展为多格式:
| 格式 | 适用场景 | 实现方式 |
|---|---|---|
| JSON | 程序间集成、管道传参 | Jackson ObjectMapper.writeValueAsString() |
| CSV | 导入 Excel / 数据分析 | 简单字符串拼接或 OpenCSV |
| HTML | 邮件报告 | 模板引擎(FreeMarker / Thymeleaf) |
| YAML | 配置管理集成 | Jackson YAML 模块 |
6.4 TLS 安全连接
生产环境的 Docker API 通常需要客户端证书认证:
bash
docker-inspector --host 192.168.3.145 --port 2376 \
--tls \
--cert client-cert.pem \
--key client-key.pem \
--ca ca.pem
技术方案:通过 SSLContext 加载 PEM 证书,注入 HttpClient.newBuilder().sslContext(ctx),将连接模式从 HTTP 升级为 HTTPS + mTLS。
6.5 容器日志与健康检查
在版本/容器/镜像基础上,增加更多数据维度:
- 容器日志尾部 :
GET /containers/{id}/logs?tail=50,快速查看最近日志 - 容器资源统计 :
GET /containers/{id}/stats?stream=false,CPU / 内存 / 网络实时数据 - 健康检查状态 :从容器详情的
State.Health字段读取,识别 unhealthy 容器 - 容器环境变量 :
GET /containers/{id}/json→Config.Env,用于配置审计(需脱敏)
6.6 持续监控模式
将一次性采集改为定时轮询,实现简易监控:
bash
docker-inspector --host 192.168.3.145 --watch --interval 30s
技术方案:ScheduledExecutorService 定时触发采集,终端清屏重绘;或将数据推送至 Prometheus Pushgateway / InfluxDB,接入 Grafana 展示。
6.7 Docker Compose / Stack 服务分组
当前输出是扁平的容器列表,可按 Compose 项目或 Swarm Stack 分组展示:
[project: hirun-iiot]
├── pascal-ming-iiot:6.0.0 running 39999/tcp
├── pascal-ming-dbsync:6.0.0 exited
├── pascal-ming-xxljob:6.0.0 running 30020/tcp
└── nodered:4.1.10-22 running 1880/tcp
[project: monitoring]
├── prometheus:v2.54.1 running 29090/tcp
├── grafana:11.2.0 running 23000/tcp
└── node-exporter:v1.8.2 running 29100/tcp
实现方式:从容器 Labels 中读取 com.docker.compose.project 进行分组。
6.8 告警与通知
增加阈值检测,发现异常自动通知:
- 容器处于 exited / restarting 状态超过 N 分钟
- 镜像版本落后于 Registry 最新版本
- 磁盘占用超过阈值(通过 Docker system df)
通知渠道:企业微信 / 钉钉 / 邮件 / Webhook。
七、已知限制
| 限制项 | 说明 |
|---|---|
| 仅支持 HTTP | 当前不支持 HTTPS/TLS,生产环境需启用 TLS 时需改造 |
| 无认证机制 | 2375 端口无认证,程序也未实现 Basic Auth 或 Token 认证 |
| 中文 Windows 终端乱码 | Windows 默认 GBK 编码,需加 -Dfile.encoding=UTF-8 运行参数 |
| 无交互能力 | 纯输出程序,不支持过滤、搜索、选择性查看 |
| 单一服务器 | 当前仅支持连接一台服务器,不支持批量 |
八、依赖清单
| 依赖 | 版本 | 用途 | 许可证 |
|---|---|---|---|
| Jackson Databind | 2.17.2 | JSON 解析 | Apache 2.0 |
| Jackson Core | 2.17.2 | JSON 底层引擎 | Apache 2.0 |
| Jackson Annotations | 2.17.2 | JSON 注解支持 | Apache 2.0 |
| Java HttpClient (JDK) | 21 | HTTP 通信 | Oracle BCL |
所有 Jackson 依赖通过 Maven 传递依赖自动引入,无需手动声明。