- 容器运行时
- 云原生
【免费下载链接】docker-ce
:warning: This repository is deprecated and will be archived (Docker CE itself is NOT deprecated) see the https://github.com/docker/docker-ce/blob/master/README.md :warning:
导读
Docker Engine API 是 Docker 引擎对外提供的 HTTP API,是docker命令行客户端与 daemon(守护进程)之间的通信桥梁,任何通过 CLI 完成的操作——包括创建容器、拉取镜像、管理网络、编排 Swarm 服务——本质上都是在调用这套 API。本指南以仓库中的 api/README.md 为核心,深入剖析 API 的单源定义文件 api/swagger.yaml、其目录结构、校验与代码生成流程,以及本地预览文档的方法;读完本文,你将掌握如何在 Docker 引擎源码中定位 API 定义、正确修改端点与对象、通过校验与生成工具保持类型与定义一致,并快速搭建本地 API 文档预览。
一、Engine API 是什么:CLI 与 daemon 之间的 HTTP 契约
Engine API 是一个由 daemon 对外提供服务的 HTTP API,Docker 命令行客户端依赖它与引擎通信,第三方软件也可以直接使用它来操控 daemon。从仓库结构看,这套 API 贯穿整个项目并落实到多个组件:
- api/swagger.yaml:API 的 Swagger 2.0(OpenAPI)定义文件,是整套 API 的单一事实来源;
- api/types/:客户端与服务端共享的各种类型定义,表示请求/响应中的对象、选项等;大部分手写,少数由 Swagger 定义自动生成;
- components/cli/cli/:命令行客户端,负责把用户命令翻译成 API 调用;
- components/engine/client/:供 CLI 与第三方 Go 程序使用的 Go 客户端库;
- components/engine/daemon/:daemon 本体,负责承载并服务这套 API。
swagger.yaml 开头的info.description把这一点说得更直白:它是 Docker Engine 提供的 HTTP API,Docker 客户端使用它来与引擎通信,因此“客户端能做到的一切,都能通过 API 完成”。例如docker ps直接对应GET /containers/json,而运行容器则是一个例外——它由多个 API 调用组合而成(先POST /containers/create创建,再POST /containers/{id}/start启动),这一点在 api/swagger.yaml 中有明确说明。
从 components/engine/api/server/ 目录可以看到服务端的实现骨架:server.go负责启动 HTTP 服务,其下的router/、httputils/、middleware/、backend/分别承担路由分发、HTTP 工具、中间件与后端业务接口的职责,共同把 Swagger 中定义的路径和 operation 落地为可执行的端点。
二、Swagger 定义:一份定义,多处复用
API 由 api/swagger.yaml 中约 1.1 万行的 Swagger 定义描述,它可以同时承担三种角色:
- 自动生成文档——包括本地预览用的 ReDoc 渲染,以及线上
docker.github.io的 API 参考文档; - 自动生成 Go 的服务端与客户端代码(进行中的工作,见下文代码生成章节);
- 提供机器可读的 API 描述——第三方工具可以据此内省 API 能力,自动生成其他语言的客户端等。
该定义文件还带有一批风格约定(见文件头注释):
- 文件使用 ReDoc 渲染,描述文本支持 GitHub Flavored Markdown;
- 不设最大行宽,便于编辑与保持 diff 清晰;
operationId采用“名词+动词”(NounVerb)格式,且名词用单数,例如ContainerList、ContainerCreate、SystemPing。
文件顶部的元信息(api/swagger.yaml)确认了当前版本:
swagger: "2.0":Swagger 2.0 规范;schemes: [http, https]:支持两种协议;produces/consumes:均为application/json与text/plain;basePath: "/v1.42":API 版本路径前缀;info.title: "Docker Engine API",info.version: "1.42"。
2.1 两个主体 section:definitions 与 paths
swagger.yaml 的主体分为两大 section,这一组织方式直接服务于编辑者的工作流:
definitions(api/swagger.yaml 起):定义可复用的请求/响应对象,例如Port、ContainerConfig、ErrorResponse、ImageSummary等;paths(api/swagger.yaml 起):定义 API 端点及其内联对象。端点内通过$ref(如$ref: "#/definitions/ErrorResponse")引用definitions中的可复用对象。
tags用于给路径分组,并决定 ReDoc 文档菜单的分组与顺序。文件注释给出了明确的约束:标签用单数、数量不宜过多(例如宁可把某个路径挂到 "System" 标签下,也不要为一个路径单建标签)。当前定义使用的标签包括 Container、Image、Network、Volume、Exec、Swarm、Node、Service、Task、Secret、Config、Plugin、System 等(api/swagger.yaml)。
2.2 端点全景:106 个 operationId
通过对 swagger.yaml 的统计,该文件共定义了106 个 operationId,覆盖容器、镜像、网络、卷、Swarm 编排、插件与系统管理等全部能力。以下是paths中的主要端点分布:
| 能力域 | 代表性端点 |
|---|---|
| 容器 | /containers/json、/containers/create、/containers/{id}/json、/containers/{id}/start、/containers/{id}/stop、/containers/{id}/logs、/containers/{id}/exec、/containers/{id}/archive、/containers/prune |
| 镜像 | /images/json、/images/create、/images/{name}/push、/images/{name}/tag、/images/search、/images/prune、/images/load、/images/get、/build、/commit |
| 网络 | /networks、/networks/create、/networks/{id}/connect、/networks/{id}/disconnect、/networks/prune |
| 卷 | /volumes、/volumes/create、/volumes/{name}、/volumes/prune |
| Exec | /containers/{id}/exec、/exec/{id}/start、/exec/{id}/resize、/exec/{id}/json |
| Swarm | /swarm/init、/swarm/join、/swarm/leave、/swarm/unlock、/services、/services/create、/services/{id}/update、/tasks、/nodes、/secrets、/configs |
| 插件 | /plugins、/plugins/pull、/plugins/{name}/enable、/plugins/{name}/push |
| 系统 | /_ping、/info、/version、/auth、/events、/system/df、/commit、/distribution/{name}/json、/session |
三、深入一个端点:以 GET /containers/json 为例
为了说明 definitions 与 paths 如何协作,这里以 GET /containers/json(operationId 为ContainerList)为例拆解:
查询参数(均位于query位置):
all(boolean,默认false):是否返回所有容器,默认只显示运行中的容器;limit(integer):返回最近创建的最多 N 个容器(含非运行容器);size(boolean,默认false):返回容器大数字段SizeRw与SizeRootFs;filters(string,JSON 编码的map[string][]string):容器列表过滤条件,例如{"status": ["paused"]}只返回暂停容器。文档列出了完整的可用过滤键:ancestor、before、expose、exited、health、id、isolation(Windows daemon 专用)、is-task、label、name、network、publish、since、status、volume。
成功响应:200返回ContainerSummary数组,并附带两个完整 JSON 示例,展示Id、Names、Image、ImageID、Command、Created、State、Status、Ports、Labels、SizeRw、SizeRootFs、HostConfig.NetworkMode、NetworkSettings.Networks以及Mounts等字段的真实形态。
错误响应:统一引用ErrorResponse定义(见 api/swagger.yaml),该定义是一个required: ["message"]的对象,仅含一个message字符串字段,例如{"message": "No such container: c2ada9df5af8"}。整套 API 的通用错误格式即是如此:HTTP 状态码表达成败,响应体为{"message": "..."}。
再以 POST /containers/create(ContainerCreate)为例可以看到更复杂的组合方式:该端点通过allOf把可复用的ContainerConfig定义与内联的HostConfig、NetworkingConfig组合成一个完整请求体,并附有超长的真实示例,涵盖Env、Cmd、Entrypoint、Image、Labels、ExposedPorts、HostConfig(Binds、CPU 参数、内存参数、PortBindings、RestartPolicy、AutoRemove、Ulimits、LogConfig等)以及NetworkingConfig.EndpointsConfig的完整配置。这正体现了文件注释所提倡的做法:definitions定义可复用对象,端点内部再以内联形式扩展不需要复用的细节。
四、维护工作流:如何更新 API 文档
4.1 核心原则:文档完全由 swagger.yaml 生成
API 文档完全由api/swagger.yaml 生成。如果 API 发生变更,唯一需要做的就是对文件本身进行修改,使其反映变更。具体编辑步骤:
- 在
paths部分找到要修改的端点; - 做出所需修改(新增字段、新增端点、调整响应等);
- 若端点需要引用可复用对象,通过
$ref指向definitions部分; - 若需要新的可复用对象,在
definitions部分定义它; - 参照文件中已有的相似模式进行模仿(例如新增字段或端点时,拷贝文件中类似的写法);
- 完整的语法参考以 Swagger 规范为准。
4.2 校验:hack/validate/swagger
修改后,hack/validate/swagger 脚本会负责验证 swagger.yaml 是否仍是合法的 Swagger 定义。该脚本的核心逻辑是:
files=($(validate_diff --diff-filter=ACMR --name-only -- 'api/swagger.yaml' || true)) if [ -n "${TEST_FORCE_VALIDATE:-}" ] || [ ${#files[@]} -gt 0 ]; then LANG=C.UTF-8 yamllint -c "${SCRIPTDIR}"/.swagger-yamllint api/swagger.yaml if out=$(swagger validate api/swagger.yaml); then echo "Congratulations! ${out}" else echo "${out}" >&2 false fi fi它通过validate_diff检测api/swagger.yaml是否有变更,若有(或设置了TEST_FORCE_VALIDATE强制校验),先运行yamllint做 YAML 规范检查,再用swagger validate做 Swagger 结构校验,校验失败时输出错误并以非零状态退出。这套校验既保证了文件语法正确,也保证了编辑者“做得正确”。
五、自动生成:从 swagger.yaml 到 Go 类型与操作
5.1 生成脚本 hack/generate-swagger-api.sh
api/types/中有一部分类型和操作代码由 swagger.yaml 自动生成,生成入口是 hack/generate-swagger-api.sh,它使用swagger generate命令完成两类生成:
模型(model)生成,从definitions生成 Go 类型文件到api/types/:
swagger generate model -f api/swagger.yaml \ -t api -m types --skip-validator -C api/swagger-gen.yaml \ -n ErrorResponse \ -n GraphDriverData \ -n IdResponse \ -n ImageDeleteResponseItem \ -n ImageSummary \ -n Plugin -n PluginDevice -n PluginMount -n PluginEnv -n PluginInterfaceType \ -n Port \ -n ServiceUpdateResponse \ -n Volume操作(operation)生成,从paths生成操作相关的类型,同样落到api/types/:
swagger generate operation -f api/swagger.yaml \ -t api -a types -m types -C api/swagger-gen.yaml \ -T api/templates --skip-responses --skip-parameters --skip-validator \ -n Authenticate \ -n ContainerChanges \ -n ContainerCreate \ -n ContainerTop \ -n ContainerUpdate \ -n ContainerWait \ -n ImageHistory \ -n VolumeCreate \ -n VolumeList布局规则由 api/swagger-gen.yaml 控制:model 生成器把每个 definition 按{{ (snakize (pascalize .Name)) }}.go的命名规则输出到api/types/;operation 生成器把每个 handler 输出到 API 包下对应子包。这两个命令在 components/engine/Makefile 中由swagger-gen目标封装,实际运行时通过镜像quay.io/goswagger/swagger:0.7.4执行。
5.2 一致性校验:hack/validate/swagger-gen
由于手写与自动生成代码并存,仓库还提供了 hack/validate/swagger-gen 校验脚本:当api/swagger.yaml或api/types/有变更时,它重新运行生成脚本,然后检查git diff -- api/types/是否为空。如果产生差异,说明开发者没有把 API 变更同步到生成代码,脚本会提示先更新 swagger.yaml、再运行hack/generate-swagger-api.sh,保证“生成结果与定义一致”作为 CI 的一项硬约束。
在 api/types/ 中可以看到两类产物的实际落点:手写部分如container/config.go、container/host_config.go、filters/parse.go、swarm/service.go、network/network.go等;而error_response.go、id_response.go、image_summary.go、plugin.go、port.go、volume.go、service_update_response.go等即为生成产物(对应上面脚本-n参数列出的定义名)。
六、查看 API 文档:本地预览与线上发布
6.1 make swagger-docs 本地预览
修改 swagger.yaml 后,可以用 Makefile 提供的swagger-docs目标快速预览渲染效果:
.PHONY: swagger-docs swagger-docs: ## preview the API documentation @echo "API docs preview will be running at http://localhost:$(SWAGGER_DOCS_PORT)" @docker run --rm -v $(PWD)/api/swagger.yaml:/usr/share/nginx/html/swagger.yaml \ -e 'REDOC_OPTIONS=hide-hostname="true" lazy-rendering' \ -p $(SWAGGER_DOCS_PORT):80 \ bfirsh/redoc:1.14.0要点:
- 运行
make swagger-docs后,预览地址为http://localhost:9000(默认端口由 components/engine/Makefile 的SWAGGER_DOCS_PORT ?= 9000决定,可用make SWAGGER_DOCS_PORT=端口号 swagger-docs覆盖); - 它通过挂载本地的 swagger.yaml 启动
bfirsh/redoc:1.14.0容器,使用 ReDoc 渲染交互式 API 文档,并通过REDOC_OPTIONS启用了hide-hostname与lazy-rendering; - README 也提示:部分样式可能不够精确,但足以确认文档生成正确。
6.2 线上文档的生产发布路径
线上 API 参考文档由 vendoring swagger.yaml 进入docker.github.io后自动生成。这意味着本地仓库中的 swagger.yaml 是唯一权威源,官方站点只是它的渲染产物——再次印证了“一切改动从 swagger.yaml 出发”的工作流。
七、进一步深入仓库
如果你希望继续深入了解 Engine API 的工程细节,建议按以下路径阅读本仓库:
- api/swagger.yaml:API 的权威定义(约 1.1 万行),
definitions从 第 175 行 开始,paths从 第 5361 行 开始; - api/types/:客户端与服务端共享的类型实现,可直接观察手写与生成代码的共存方式;
- api/server/:服务端 HTTP 层实现,包含
server.go、router/、httputils/、middleware/与backend/; - client/:Go 客户端库,CLI 与第三方 Go 程序都基于它调用 API;
- hack/generate-swagger-api.sh、hack/validate/swagger、hack/validate/swagger-gen:定义的生成与校验闭环;
- api/swagger-gen.yaml:代码生成布局规则;
- components/engine/Makefile:
swagger-docs本地预览入口。
结语
Engine API 是 Docker 生态的“协议枢纽”:CLI 的一切命令、第三方程序对引擎的任意操控,最终都汇聚到 api/swagger.yaml 这份单一定义之上。对开发者而言,理解definitions与paths的分工、遵循“改定义 → 校验 → 重新生成”的工作流,并在 api/types/ 中保持手写与生成代码的一致,就把握住了维护这套 API 的全部关键;而make swagger-docs则提供了修改后即时验证渲染效果的轻量反馈环。
- 容器运行时
- 云原生
【免费下载链接】docker-ce
:warning: This repository is deprecated and will be archived (Docker CE itself is NOT deprecated) see the https://github.com/docker/docker-ce/blob/master/README.md :warning:
相关推荐
Moby Engine API:基于 Swagger 驱动的 Docker Engine HTTP API 设计、文档生成与开发流程
Moby Engine API:基于 Swagger 驱动的 Docker Engine HTTP API 设计、文档生成与开发流程 本文以 api/READM
云原生容器运行时虚拟化容器编排Docker Engine API 与 Swagger 定义:从 api/swagger.yaml 到 Go 客户端与文档生成
Docker Engine API 与 Swagger 定义:从 api/swagger.yaml 到 Go 客户端与文档生成 Docker Engine AP
静态分析代码质量Lint开发工具Apache Mesos 分配器模块(Allocation Modules)实战指南:从 Allocator 接口到自定义资源分配策略
Apache Mesos 分配器模块(Allocation Modules)实战指南:从 Allocator 接口到自定义资源分配策略 Mesos master
云原生集群管理容器编排任务调度
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考