Moby Remote API v1.15 全解:容器、镜像、Exec 端点与 Hijack 流协议详解
本文基于 Moby 仓库中的 Remote API v1.15 规范文档,系统梳理该版本 Engine Remote API 的完整端点体系:容器生命周期管理、镜像拉取/推送/导出、构建、事件监听与 Exec 执行,以及 attach 场景下基于 8 字节头帧的 stdout/stderr 多路复用流协议。读完本文,你能够直接使用 curl 或自研客户端对接 Docker Engine 的 v1.15 HTTP API,理解每个端点的请求参数、响应格式与状态码,并掌握底层调用链(如 docker run 背后的 API 组合)。
1. 总览:v1.15 时代 Remote API 的设计基调
v1.15 文档开篇明确了 Remote API 的三条基本设定,这也是理解该版本一切端点行为的前提:
- Remote API 已取代旧的
rcli客户端协议:所有与 Engine 的交互统一走 HTTP,不再依赖私有 RPC 协议; - 默认监听 Unix Socket:daemon 默认监听
unix:///var/run/docker.sock,也可以通过绑定参数把 Docker 挂到另一个 host/port 或另一个 Unix socket 上(即后来dockerd -H参数所表达的能力); - REST 为主,hijack 为辅:API 大体遵循 REST 风格,但
attach、pull等需要双向流式传输的命令会劫持(hijack)HTTP 连接,把STDIN、STDOUT、STDERR直接跑在同一条连接上。
这一设计区分对客户端实现影响很大:普通端点可以按标准 REST 方式解析 JSON 响应;而流式端点的响应体是自定义二进制帧格式(见第 5 节),必须按协议解析。Moby 仓库中的 api/pkg/stdcopy 即为这类多路复用流的 Go 侧实现支撑,与文档中描述的帧格式相对应。
适用前提说明:本文所有端点行为、状态码与字段均以 api/docs/v1.15.md 的记载为准,属于历史版本(v1.15 期)的 API 语义;当前仓库主线已演进到 v1.49 等更新版本,字段结构(如日志的 JSON 流、inspect 输出)有变化。若对接现代 daemon,请以对应版本的 API 文档为准。
2. 容器端点(Containers)
容器是 v1.15 API 的绝对主体,覆盖“列表 → 创建 → 检视 → 生命周期 → 流式接入 → 删除”的完整闭环。
2.1 列出容器:GET /containers/json
示例请求(通过 all、before、size 组合过滤并附带体积信息):
GET /containers/json?all=1&before=8dfafdbc3a40&size=1 HTTP/1.1
响应为 JSON 数组,每个元素的关键字段:
| 字段 | 含义 |
|---|---|
Id |
容器短 ID(如 8dfafdbc3a40) |
Names |
名称列表(带 / 前缀,如 ["/boring_feynman"]) |
Image |
镜像引用,如 ubuntu:latest |
Command |
命令行的简短描述 |
Created |
创建时间(Unix 秒) |
Status |
状态描述,如 Exit 0 |
Ports |
端口映射,元素形如 {"PrivatePort": 2222, "PublicPort": 3333, "Type": "tcp"} |
SizeRw / SizeRootFs |
读写层 / 根文件系统大小(仅在 size=1 时填充) |
查询参数:
- all –
1/True/true或0/False/false,是否显示全部容器。默认只显示运行中的容器(默认false); - limit – 只显示最近创建的
limit个容器(包含非运行态); - since – 只显示该 Id 之后创建的容器(包含非运行态);
- before – 只显示该 Id 之前创建的容器(包含非运行态);
- size – 是否在结果中携带容器大小;
- filters – JSON 编码的过滤器(
map[string][]string)。v1.15 支持的过滤器:exited=<int>:退出码为<int>的容器;status=(restarting|running|paused|exited):按状态过滤。
状态码:200 无错误;400 参数非法;500 服务器错误。
2.2 创建容器:POST /containers/create
这是 v1.15 中参数最重的端点,请求体同时携带容器配置与HostConfig(主机侧配置)。文档给出的完整示例:
POST /containers/create HTTP/1.1
Content-Type: application/json
{
"Hostname": "",
"Domainname": "",
"User": "",
"Memory": 0,
"MemorySwap": 0,
"CpuShares": 512,
"Cpuset": "0,1",
"AttachStdin": false,
"AttachStdout": true,
"AttachStderr": true,
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"FOO=bar",
"BAZ=quux"
],
"Cmd": [
"date"
],
"Entrypoint": "",
"Image": "ubuntu",
"Volumes": {
"/tmp": {}
},
"WorkingDir": "",
"NetworkDisabled": false,
"MacAddress": "12:34:56:78:9a:bc",
"ExposedPorts": {
"22/tcp": {}
},
"SecurityOpt": [],
"HostConfig": {
"Binds": ["/tmp:/tmp"],
"Links": ["redis3:redis"],
"LxcConf": {"lxc.utsname":"docker"},
"PortBindings": { "22/tcp": [{ "HostPort": "11022" }] },
"PublishAllPorts": false,
"Privileged": false,
"Dns": ["8.8.8.8"],
"DnsSearch": [""],
"ExtraHosts": null,
"VolumesFrom": ["parent", "other:ro"],
"CapAdd": ["NET_ADMIN"],
"CapDrop": ["MKNOD"],
"RestartPolicy": { "Name": "", "MaximumRetryCount": 0 },
"NetworkMode": "bridge",
"Devices": []
}
}
成功响应(注意 201 Created 返回的是完整容器 Id 与告警列表):
HTTP/1.1 201 Created
Content-Type: application/json
{
"Id": "f91ddc4b01e079c4481a8340bbbeca4dbd33d6e4a10662e499f8eacbb5bf252b"
"Warnings": []
}
JSON 参数逐项说明(容器配置部分):
- Hostname – 容器主机名;
- Domainname – 容器域名;
- User – 容器内运行用户;
- Memory – 内存限制(字节);
- MemorySwap – 内存 + swap 总限制,
-1表示 swap 无限; - CpuShares – 相对 CPU 权重(与其他容器相比的相对权重);
- CpuSet – 使用的 cgroups cpuset;
- AttachStdin / AttachStdout / AttachStderr – 是否附着到对应标准流;
- Tty – 是否把标准流挂到 tty(含未关闭的 stdin);
- OpenStdin – 是否打开 stdin;
- StdinOnce – 第一个附着客户端断开后关闭 stdin;
- Env –
["VAR=value", "VAR2=value2"]形式的环境变量列表; - Cmd – 要执行的命令(字符串或字符串数组);
- Entrypoint – 容器入口点(字符串或数组);
- Image – 所用镜像名;
- Volumes – 挂载点路径到空对象的映射;
- WorkingDir – 工作目录;
- NetworkDisabled –
true时禁用容器网络; - MacAddress – 指定 MAC 地址;
- ExposedPorts – 端口到空对象的映射,形如
"22/tcp": {}; - SecurityOpt – 为 MLS(如 SELinux)自定义标签的字符串列表。
HostConfig 子参数(决定容器与宿主机的关系):
- Binds – 卷绑定列表,元素格式为
container_path(新建卷)、host_path:container_path(绑定挂载)或host_path:container_path:ro(容器内只读); - Links – 链接列表,元素形如
container_name:alias; - LxcConf – LXC 专属配置,仅在使用
lxc执行驱动时生效; - PortBindings – 容器暴露端口到宿主端口的映射,形如
{ "<port>/<protocol>": [{ "HostPort": "<port>" }] };注意 port 是字符串而非整数; - PublishAllPorts – 为所有暴露端口随机分配宿主端口;
- Privileged – 给予容器对宿主机的完全访问;
- Dns / DnsSearch – DNS 服务器 / 搜索域列表;
- ExtraHosts – 追加到容器
/etc/hosts的["hostname:IP"]映射; - VolumesFrom – 从其他容器继承卷,形如
<container name>[:<ro|rw>]; - CapAdd / CapDrop – 增删内核 capabilities;
- RestartPolicy – 退出后的重启策略:
Name为"always"(总是重启)或"on-failure"(退出码非零才重启);用on-failure时由MaximumRetryCount控制重试次数;默认不重启。为防止重启风暴,每次重启前会加入倍增延迟(从 100ms 起步、逐次翻倍); - NetworkMode – 网络模式,支持
bridge、host、none、container:<name|id>; - Devices – 设备列表,元素形如
{ "PathOnHost": "/dev/deviceName", "PathInContainer": "/dev/deviceName", "CgroupPermissions": "mrw"}。
查询参数:
- name – 给容器指定名称,须匹配
/?[a-zA-Z0-9_-]+。
状态码:201 无错误;404 无此容器;406 无法 attach(容器未运行);500 服务器错误。
2.3 检视容器:GET /containers/(id or name)/json
返回容器的低层信息,包括 Config(创建时配置)、State(运行态)、Image(完整镜像 Id)、NetworkSettings 与 HostConfig 等。v1.15 响应示例(节选):
{
"Id": "4fa6e0f0c6786287e131c3852c58a2e01cc697a68231826813597e4994f1d6e2",
"Created": "2013-05-07T14:51:42.041847+02:00",
"Path": "date",
"Args": [],
"Config": {
"Hostname": "4fa6e0f0c678",
"User": "",
"Memory": 0,
"MemorySwap": 0,
"AttachStdin": false,
"AttachStdout": true,
"AttachStderr": true,
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": null,
"Cmd": ["date"],
"Image": "ubuntu",
"Volumes": {},
"WorkingDir": ""
},
"State": {
"Running": false,
"Pid": 0,
"ExitCode": 0,
"StartedAt": "2013-05-07T14:51:42.087658+02:01360",
"Ghost": false
},
"Image": "b750fe79269d2ec9a3c593ef05b4332b1d1a02a62b4accb2c21d589ff2f5f2dc",
"NetworkSettings": {
"IpAddress": "",
"IpPrefixLen": 0,
"Gateway": "",
"Bridge": "",
"PortMapping": null
},
"HostConfig": {
"Privileged": false,
"PortBindings": {
"80/tcp": [{ "HostIp": "0.0.0.0", "HostPort": "49153" }]
},
"Links": ["/name:alias"],
"PublishAllPorts": false,
"CapAdd": ["NET_ADMIN"],
"CapDrop": ["MKNOD"]
}
}
可以看到该版本的 inspect 输出里还保留着 Ghost 这类早期字段——这是研究 API 演化(对照 CHANGELOG)的典型样本。状态码:200 / 404 / 500。
2.4 容器内进程、日志与文件系统
列出进程 GET /containers/(id or name)/top:在 Unix 系统上通过执行 ps 实现,Windows 不支持。查询参数 ps_args 指定 ps 参数(如 aux),默认 -ef。响应为 Titles(表头)+ Processes(行数组)结构:
GET /containers/4fa6e0f0c678/top?ps_args=aux HTTP/1.1
{
"Titles" : ["USER","PID","%CPU","%MEM","VSZ","RSS","TTY","STAT","START","TIME","COMMAND"],
"Processes" : [
["root","13642","0.0","0.1","18172","3184","pts/0","Ss","17:03","0:00","/bin/bash"],
["root","13895","0.0","0.0","4348","692","pts/0","S+","17:15","0:00","sleep 10"]
]
}
获取日志 GET /containers/(id or name)/logs,响应 Content-Type 为 application/vnd.docker.raw-stream:
GET /containers/4fa6e0f0c678/logs?stderr=1&stdout=1×tamps=1&follow=1&tail=10 HTTP/1.1
查询参数:follow(是否流式返回,默认 false)、stdout / stderr(分别显示对应流,默认 false)、timestamps(每行打印时间戳,默认 false)、tail(输出末尾 all 或 <number> 行,默认 all)。状态码:200 / 404 / 500。
检视文件系统变更 GET /containers/(id or name)/changes:返回 Path + Kind 数组,Kind 为数字枚举(0/1 分别表示不同类型变更):
[
{ "Path": "/dev", "Kind": 0 },
{ "Path": "/dev/kmsg", "Kind": 1 },
{ "Path": "/test", "Kind": 1 }
]
导出容器 GET /containers/(id or name)/export:以 application/octet-stream 返回容器的 tar 流。
调整 TTY 尺寸 GET /containers/(id or name)/resize?h=<height>&w=<width>:如 ?h=40&w=80,成功返回 200 且 Content-Length 为 0;500 表示坏文件描述符。
2.5 生命周期操作
以下端点都是“动作型”端点,成功后统一返回 204 No Content:
| 端点 | 作用 | 关键查询参数 | 特有状态码 |
|---|---|---|---|
POST /containers/(id)/start |
启动容器 | 无(v1.15 允许在 body 携带与创建时相同的 HostConfig 字段做启动期修订) | 304 已在运行 |
POST /containers/(id)/stop |
停止容器 | t – 强制 kill 前等待的秒数 | 304 已停止 |
POST /containers/(id)/restart |
重启容器 | t – kill 前等待秒数 | — |
POST /containers/(id)/kill |
杀死容器 | signal – 发送的信号(整数或 "SIGINT" 等);不设置时按 SIGKILL 处理并等待容器退出 |
— |
POST /containers/(id)/pause |
暂停容器 | — | — |
POST /containers/(id)/unpause |
恢复容器 | — | — |
POST /containers/(id)/wait |
阻塞至容器停止并返回退出码 | — | 见下 |
wait 的响应是一个 JSON 对象 {"StatusCode": 0},这是脚本化场景里拿退出码的标准方式。所有端点均共享 404(无此容器)与 500(服务器错误);start 端点文档还列出:在启动时 body 中可携带 Binds、Links、PortBindings、Privileged、Dns、VolumesFrom、CapAdd、CapDrop、RestartPolicy、NetworkMode、Devices 等字段(语义与创建时 HostConfig 一致),用于在启动阶段再修订一次主机侧配置。
2.6 等待与删除
删除容器 DELETE /containers/(id or name),查询参数:
- v – 是否同时删除关联卷(默认 false);
- force – 先 kill 再删除(默认 false)。
状态码:204 无错误、400 参数非法、404 无此容器、500 服务器错误。
从容器拷贝文件 POST /containers/(id or name)/copy,请求体指定资源路径,响应为 tar 流:
POST /containers/4fa6e0f0c678/copy HTTP/1.1
Content-Type: application/json
{
"Resource": "test.txt"
}
HTTP/1.1 200 OK
Content-Type: application/x-tar
3. 流式接入:attach 与多路复用协议(重点)
attach 是 v1.15 中最需要客户端认真实现的端点。
3.1 POST /containers/(id or name)/attach
POST /containers/16253994b7c4/attach?logs=1&stream=0&stdout=1 HTTP/1.1
查询参数(均为 1/True/true 或 0/False/false,默认 false):
- logs – 是否返回历史日志;
- stream – 是否返回实时流;
- stdin –
stream=true时是否接入 stdin; - stdout / stderr –
logs=true时返回对应日志;stream=true时接入对应流。
状态码:200 / 400(参数非法)/ 404 / 500。
3.2 帧格式:Header + Payload
文档对流的二进制格式有精确定义,这是客户端实现的关键:
- 若创建容器时启用了 Tty:流是进程 PTY 与客户端 stdin 的原始数据,无帧结构,直接读即可;
- 若 未启用 Tty:stdout 与 stderr 被多路复用到同一条流上,每一帧由 Header + Payload 组成。
Header 共 8 字节,Go 伪码表示为:
header := [8]byte{STREAM_TYPE, 0, 0, 0, SIZE1, SIZE2, SIZE3, SIZE4}
- 第 1 字节
STREAM_TYPE:0= stdin(写往 stdout 侧)、1= stdout、2= stderr; - 第 2–4 字节固定为 0;
- 最后 4 字节
SIZE1..SIZE4为**大端(big endian)**编码的 uint32 帧载荷长度; - Payload 紧随其后,为原始流数据。
文档给出的最简实现步骤:
- 读 8 字节头;
- 按第 1 字节选择输出到 stdout 或 stderr;
- 从最后 4 字节取出帧大小;
- 读取该大小的数据并输出到正确的一路;
- 回到第 1 步循环。
在 Moby 仓库中,这一帧协议的 Go 侧读写实现集中在 api/pkg/stdcopy(从源码结构看,stdcopy 包即围绕这种“带 8 字节头的 stdio 多路复用”提供读写工具),自研客户端可直接参考其语义。
3.3 WebSocket 变体:GET /containers/(id or name)/attach/ws
GET /containers/e90e34656806/attach/ws?logs=0&stream=1&stdin=1&stdout=1&stderr=1 HTTP/1.1
按 RFC 6455 完成 WebSocket 握手,随后在同一连接上传输相同的流数据。查询参数、状态码与 HTTP 版 attach 完全一致。对于浏览器端或无法处理裸 TCP 流的场景,这是 v1.15 提供的接入通道。
3.4 POST /containers/(id or name)/wait
阻塞直到容器停止,返回 {"StatusCode": 0}(200);404、500 同上。与 attach 的区别在于:wait 不传任何流,只取退出码,适合编排系统做生命周期收尾判断。
4. 镜像端点(Images)
4.1 列出镜像:GET /images/json
GET /images/json?all=0 HTTP/1.1
响应示例:
[
{
"RepoTags": ["ubuntu:12.04", "ubuntu:precise", "ubuntu:latest"],
"Id": "8dbd9e392a964056420e5d58ca5cc376ef18e2de93b5cc90e868a1bbc8318c1c",
"Created": 1365714795,
"Size": 131506275,
"VirtualSize": 131506275
},
{
"RepoTags": ["ubuntu:12.10", "ubuntu:quantal"],
"ParentId": "27cf784147099545",
"Id": "b750fe79269d2ec9a3c593ef05b4332b1d1a02a62b4accb2c21d589ff2f5f2dc",
"Created": 1364102658,
"Size": 24653,
"VirtualSize": 180116135
}
]
注意 Size(本层增量)与 VirtualSize(含父层的总大小)的区分——这是分层存储模型在 API 层的直接体现。
查询参数:all(默认 false,是否包含中间层/未标记镜像)、filters(JSON 编码,v1.15 可用 dangling=true 过滤悬空镜像)、filter(按名称过滤)。
4.2 创建(拉取/导入)镜像:POST /images/create
该端点一身二职:从 registry 拉取或从源导入:
POST /images/create?fromImage=ubuntu HTTP/1.1
HTTP/1.1 200 OK
Content-Type: application/json
{"status": "Pulling..."}
{"status": "Pulling", "progress": "1 B/ 100 B", "progressDetail": {"current": 1, "total": 100}}
{"error": "Invalid..."}
...
响应体是逐行 JSON(JSON lines)的进度流:status 行推进进度,error 行报告失败——客户端需逐行解析而非等待整体响应。
查询参数:
- fromImage – 要拉取的镜像名;
- fromSrc – 导入源,可为 URL 或
-(从请求体读取镜像内容); - repo / tag – 仓库与标签。
请求头:X-Registry-Auth – base64 编码的 AuthConfig 对象,用于私有仓库认证。状态码:200 / 500。
4.3 检视与历史
GET /images/(name)/json 返回镜像低层信息,含 ContainerConfig(制作该层时的容器配置)、Id、Parent、Size、Created 等;状态码 200 / 404(无此镜像)/ 500。
GET /images/(name)/history 返回镜像历史链(每层的 Id、Created、CreatedBy):
[
{ "Id": "b750fe79269d", "Created": 1364102658, "CreatedBy": "/bin/bash" },
{ "Id": "27cf78414709", "Created": 1364068391, "CreatedBy": "" }
]
4.4 推送、打标签、删除与搜索
推送 POST /images/(name)/push(可选查询参数 tag,请求头 X-Registry-Auth)。响应同样是 JSON lines 进度流:
{"status": "Pushing..."}
{"status": "Pushing", "progress": "1/? (n/a)", "progressDetail": {"current": 1}}
推送到私有 registry 时,镜像必须先 tag 成引用该 registry 主机名与端口的仓库名,URL 中使用该仓库名(与 CLI 流程一致):
POST /images/registry.acme.com:5000/test/push HTTP/1.1
状态码:200 / 404 / 500。
打标签 POST /images/(name)/tag,查询参数:repo(目标仓库)、force(默认 false)、tag(新标签名)。成功返回 201;另有 400、404、409(冲突)、500。
删除 DELETE /images/(name),查询参数 force、noprune(均默认 false)。响应是逐条操作结果数组——先 untag 再逐层删除:
[
{"Untagged": "3e2f21a89f"},
{"Deleted": "3e2f21a89f"},
{"Deleted": "53b4f83ac9"}
]
状态码:200 / 404 / 409 / 500。
搜索 GET /images/search?term=sshd:在 Docker Hub 上搜索。v1.15 文档特别注明:响应键名自 v1.6 起改变,改为直接透传 registry 服务器返回给 daemon 的 JSON。响应字段为 description、is_official、is_automated、name、star_count。
4.5 镜像的导出与加载(Save / Load)
导出单仓库 GET /images/(name)/get:返回包含该仓库所有镜像与元数据的 tarball(application/x-tar 二进制流)。若 name 是具体名+tag(如 ubuntu:latest),只返回该镜像及其父层;若是镜像 ID,同样只返回该镜像及父层,但 tarball 中不含 repositories 文件(因为没有镜像名可引用)。
导出多仓库 GET /images/get?names=<urlencoded name>&names=...:对每个 names 参数按上述规则打包。
加载 POST /images/load:请求体为 tarball,把一组镜像与标签载入本地仓库,成功返回 200。
镜像 tarball 格式(get/load 双方共同遵守的容器格式):
- 每个镜像层一个目录(以长 ID 命名),内含三个文件:
VERSION:文件格式版本(当时为1.0);json:该层的详细信息(类似docker inspect layer_id的输出);layer.tar:该层的文件系统变更 tar 包。
layer.tar内使用 aufs 风格的.wh..wh.aufs文件与目录来表达属性变更和删除(白名单/删除标记机制);- 若 tarball 定义了仓库,根目录还会有
repositories文件,内容是把“仓库:tag”映射到层 ID 的 JSON,例如:
{"hello-world":
{"latest": "565a9d68a73f6706862bfe8409a7f659776d4d60a8d096eb4a3cbce6999cc2a1"}
}
这套格式是后来 docker save/docker load 离线分发镜像的底层协议基础。
5. 构建、认证与系统级端点(Misc)
5.1 POST /build:从 tar 流构建镜像
POST /build HTTP/1.1
请求体是一个 tar 归档(支持 identity/gzip/bzip2/xz 压缩),根目录必须包含名为 Dockerfile 的文件;归档中其他文件进入构建上下文,可被 ADD 指令引用。
响应为 JSON lines 流,逐行返回 stream 行与可能的 error/errorDetail 行:
{"stream": "Step 1..."}
{"stream": "..."}
{"error": "Error...", "errorDetail": {"code": 123, "message": "Error..."}}
查询参数:t(成功时应用于结果镜像的仓库名:tag)、remote(git 或 HTTP/HTTPS 构建源 URI)、q(静默冗长输出)、nocache(不用缓存)、rm(成功构建后删除中间容器,默认行为)、forcerm(总是删除中间容器,蕴含 rm)。
请求头:Content-type 应为 application/tar;X-Registry-Config – base64 编码的 ConfigFile 对象。状态码:200 / 500。
5.2 POST /auth:校验认证配置
请求体为 registry 认证四元组(username / password / email / serveraddress),daemon 用它向 registry 验证凭据有效性,成功返回 200(或 204),失败 500。这是 docker login 的 API 底座。
5.3 GET /info:系统级信息
响应包含守护进程的全局状态,v1.15 示例:
{
"Containers": 11,
"Images": 16,
"Driver": "btrfs",
"ExecutionDriver": "native-0.1",
"KernelVersion": "3.12.0-1-amd64",
"Debug": false,
"NFd": 11,
"NGoroutines": 21,
"NEventsListener": 0,
"InitPath": "/usr/bin/docker",
"IndexServerAddress": ["https://index.docker.io/v1/"],
"MemoryLimit": true,
"SwapLimit": false,
"IPv4Forwarding": true
}
字段覆盖:容器/镜像计数、存储驱动、内核版本、打开 fd 数、goroutine 数、事件监听器数、内存限制与 swap 限制是否可用、IPv4 转发状态等。监控面板与排障时这是首选端点。
5.4 GET /version 与 GET /_ping
GET /version 返回 daemon 的 API 版本与构建信息(ApiVersion、Version、GitCommit、GoVersion)——任何 API 客户端在开始工作前都应以它做能力协商。GET /_ping 是存活探针,正常返回纯文本 OK(Content-Type: text/plain)。
5.5 POST /commit:从容器变更创建镜像
POST /commit?container=44c004db4b17&comment=message&repo=myrepo HTTP/1.1
Content-Type: application/json
{ ... 新镜像的容器配置(Hostname、User、Memory、CpuShares、Env、Cmd、Volumes、WorkingDir、ExposedPorts 等) ... }
查询参数:container(源容器)、repo、tag、comment(提交说明)、author(作者,如 "John Hannibal Smith")。成功返回 201 Created 及新镜像 Id:{"Id": "596069db4bf5"}。状态码:201 / 404 / 500。
5.6 GET /events:事件流
可流式实时订阅,也可用 since 时间戳轮询。v1.15 中容器会报告事件:
create, destroy, die, export, kill, pause, restart, start, stop, unpause
镜像会报告:
untag, delete
请求与响应示例:
GET /events?since=1374067924
{"status": "create", "id": "dfdf82bd3881","from": "ubuntu:latest", "time":1374067924}
{"status": "start", "id": "dfdf82bd3881","from": "ubuntu:latest", "time":1374067924}
{"status": "stop", "id": "dfdf82bd3881","from": "ubuntu:latest", "time":1374067966}
{"status": "destroy", "id": "dfdf82bd3881","from": "ubuntu:latest", "time":1374067970}
查询参数:since / until(轮询用的时间戳)。状态码:200 / 500。
6. Exec 系列端点
Exec 在 v1.15 中已拆成“创建 → 启动 →(可选)调整 TTY”三步,这是理解 docker exec 实现的关键。
6.1 Exec Create:POST /containers/(id or name)/exec
在运行中的容器内布置一个 exec 实例:
POST /containers/e90e34656806/exec HTTP/1.1
Content-Type: application/json
{
"AttachStdin": false,
"AttachStdout": true,
"AttachStderr": true,
"Tty": false,
"Cmd": ["date"]
}
HTTP/1.1 201 Created
Content-Type: application/json
{ "Id": "f90e34656806" }
JSON 参数:AttachStdin / AttachStdout / AttachStderr(接入 exec 命令的对应流)、Tty(分配伪终端)、Cmd(命令,字符串或数组)。状态码:201 / 404。
6.2 Exec Start:POST /exec/(id)/start
POST /exec/e90e34656806/start HTTP/1.1
Content-Type: application/json
{ "Detach": false, "Tty": false }
Detach 为 true 时 API 在 exec 命令启动后即返回;否则建立交互式会话,响应为 application/vnd.docker.raw-stream 的 {{ STREAM }}。流的行为与 attach API 相同——即第 3.2 节的 8 字节头帧多路复用格式(Tty 开启时则为原始流)。状态码:200 / 404。
6.3 Exec Resize:POST /exec/(id)/resize
调整 exec 会话的 tty 尺寸,查询参数 h(高度)/w(宽度);仅当 exec 创建与启动时指定了 tty 才有效。成功返回 201;404 表示无此 exec 实例。
7. 组合视角:docker run 背后的 API 调用链
v1.15 文档专门用一节拆解了 docker run 命令行如何组合上述端点,这是把离散端点串成工作流的权威参考:
- Create the container——调用
POST /containers/create; - 若返回 404(镜像不存在):先尝试
POST /images/create拉取,然后重试创建容器; - Start the container——调用
POST /containers/(id)/start; - 若非分离模式:
POST /containers/(id)/attach,参数logs=1&stream=1(logs=1保证拿到容器启动以来已有的 stdout/stderr,stream=1保证接续实时流); - 若分离模式或仅接入了 stdin:打印容器 Id。
这一段说明了两件事:一是“create 失败→拉取→重试”这种幂等重试模式是官方客户端的标准容错路径;二是 attach 同时打开 logs 与 stream 才能避免“启动瞬间的输出”丢失——自研编排工具复刻 docker run 语义时务必照此实现。
8. Hijacking 与 CORS
- Hijacking:v1.15 的
/attach(及同协议的 exec start、logs follow 等)通过劫持同一 HTTP 连接来同时传输 stdin、stdout、stderr。文档明确提示“这一行为未来可能改变”,因此客户端实现时不应把 TCP 层细节当作长期契约,而应依赖帧协议(第 3.2 节)做解析。 - CORS:允许跨域访问 Remote API 需在 daemon 模式启动时添加
--api-enable-cors参数,例如:
$ docker -d -H="192.168.1.9:2375" --api-enable-cors
9. 小结
v1.15 版 Remote API 文档刻画了 Docker Engine 早期 HTTP 化阶段的完整面貌:容器、镜像两大资源域各 8~10 个端点,外加 build、auth、info、version、ping、commit、events、save/load 与 exec 三类支撑端点;技术特征上则是“REST + JSON lines 进度流 + 8 字节头帧的 hijack 二进制流”三种响应模式的组合。对接这一版本 API 时,重点在于三处:
- 状态码语义——
304(already started/stopped)、404触发拉取重试、406(impossible to attach)等细节决定客户端状态机怎么写; - 流式协议——attach/exec start 的帧解析必须区分 Tty 开/关两种形态;
- 认证头——拉取与推送统一使用
X-Registry-Auth(base64 AuthConfig),构建使用X-Registry-Config(base64 ConfigFile)。
如需进一步对照该版本与后续版本的差异,可查阅 api/docs/CHANGELOG.md 以及仓库中更高版本(如 v1.49)的 API 定义;流协议的 Go 实现可参考 api/pkg/stdcopy/stdcopy.go。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00