Docker API图像创建/拉动(/v1.6/images/create)显然总是返回
HTTP/1.1 200 OK
Content-Type: application/json
无论过程是成功还是失败。
此外,有效载荷无效json。
例如:/v1.6/images/create?fromImage = whatevertheflush
返回:
{"status":"Pulling repository whatevertheflush"}{"error":"Server error: 404 trying to fetch remote history for whatevertheflush","errorDetail":{"code":404,"message":"Server error: 404 trying to fetch remote history for whatevertheflush"}}
不是有效的json,并且没有转发/使用HTTP错误使得处理客户端错误变得很麻烦。
确实,docker-py只是呕吐有效载荷(https://github.com/dotcloud/docker-py/blob/master/docker/client.py#L374)。来自openstack的DockerHTTPClient尝试根据http错误代码返回一个值,该代码始终为200 ...(https://github.com/openstack/nova/blob/master/nova/virt/docker/client.py#L191)
现在,我理解拉动可能需要很长时间,并且开始向客户端传输答案有点意义,但我不禁想到这里出了问题。
所以,这有三个方面:
答案 0 :(得分:2)
这个问题有点老了,但是对于将来登陆此页面的未来读者,我想让您知道您并不孤单,我们会感到痛苦。这个API确实看起来很糟糕。
TL; DR回答为“ /images/create
响应格式未记录;创建调用完成后,丢弃输出并查询/images/XXX/json
。”
几年前,我编写了一些编排工具,但发现/images/create
API非常烦人。但是,让我们开始吧:
200
响应中没有记录的架构; v1.19文档仅提供了一些记录的示例。 v1.37(在我撰写本文时是最新的)文档甚至没有走那么远,在所有响应中都没有提供详细信息。Transfer-Encoding: chunked
的形式发送,并且所发送的每条记录都以十六进制的字节数开头。这是一个低级摘录(绕过curl,所以我们可以看到实际发送的是什么): host-4:~ rg$ telnet localhost 2375
Trying ::1...
Connected to localhost.
Escape character is '^]'.
POST /images/create?fromImage=jenkins/jenkins:latest HTTP/1.1
Host: localhost:2375
User-Agent: foo/1.0
Accept: */*
HTTP/1.1 200 OK
Api-Version: 1.39
Content-Type: application/json
Docker-Experimental: true
Ostype: linux
Server: Docker/18.09.1 (linux)
Date: Wed, 06 Feb 2019 16:53:19 GMT
Transfer-Encoding: chunked
39
{"status":"Pulling from jenkins/jenkins","id":"latest"}
5e
{"status":"Digest: sha256:abd3e3f96fbc3445c420fda590f37e2bd3377f69affd47b63b3d826d084c5ddc"}
45
{"status":"Status: Image is up to date for jenkins/jenkins:latest"}
0
200 OK
,不代表成功或失败。 (鉴于调用的性质,我想它可能应该返回202 Accepted
。理想情况下,我们会得到一个Location
标头,指向可用于查询进度/状态。)curl -Nv -X POST http://yourdocker:2375/images/create?fromImage=jenkins/jenkins:latest -o /tmp/omgwtf.txt
。你会惊讶的。大量的带宽浪费在传输服务器渲染的ASCII条形图上!! 。实际上,记录以三种不同的方式返回每一层的进度,即当前和总字节的数字字段,条形图以及以MB或GB为单位的漂亮打印字符串。为什么这不只是呈现在客户端上?好问题。>
字符的随机转义的unicode rep,尽管它安全地位于JSON字符串中。有人只是在墙上扔逃生电话,看看有什么卡住了? ¯\ _(ツ)_ /¯id
字段可以更改其引用的内容,而知道该记录的唯一方法就是解析人类可读的字符串。 Pulling from XXX
vs Pulling fs layer
vs Downloading
等。据我所知,知道是否完成的唯一真实方法是跟踪所有id,并确保获得{{1 }},以关闭套接字。Pull complete
,但是我不确定是否有多种可能的答案。Status: Downloaded newer image for XXX
声称完成之后,您可能会很幸运地请求/images/XXX/json
。这两个调用的结合将非常可靠地表明/images/create
是否有效。这是一个较长的串联客户端响应块,其中显示了一些不同的记录类型。为简洁起见,进行了编辑:
/images/create
此代码现在可以运行Internet。 = 8-O
答案 1 :(得分:0)
此特定端点实际上返回分块编码。卷曲的一个例子:
$ curl -v -X POST http://localhost:4243/images/create?fromImage=base
* About to connect() to localhost port 4243 (#0)
* Trying ::1...
* Connection refused
* Trying 127.0.0.1...
* connected
* Connected to localhost (127.0.0.1) port 4243 (#0)
> POST /images/create?fromImage=base HTTP/1.1
> User-Agent: curl/7.24.0 (x86_64-apple-darwin12.0) libcurl/7.24.0 OpenSSL/0.9.8y zlib/1.2.5
> Host: localhost:4243
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Type: application/json
< Date: Fri, 07 Feb 2014 04:21:59 GMT
< Transfer-Encoding: chunked
<
* Connection #0 to host localhost left intact
{"status":"Pulling repository base"}{"status":"Pulling image (ubuntu-quantl) from base","progressDetail":{},"id":"b750fe79269d"}{"status":"Pulling image (ubuntu-quantl) from base, endpoint: https://cdn-registry-1.docker.io/v1/","progressDetail":{},"id":"b750fe79269d"}{"status":"Pulling dependent layers","progressDetail":{},"id":"b750fe79269d"}{"status":"Download complete","progressDetail":{},"id":"27cf78414709"}{"status":"Download complete","progressDetail":{},"id":"b750fe79269d"}{"status":"Download complete","progressDetail":{},"id":"b750fe79269d"}* Closing connection #0
现在我不确定你是如何在Python中解析它的,但是在Ruby中,我可以这样使用Yajl:
parts = []
Yajl::Parser.parse(body) { |o| parts << o }
puts parts
{"status"=>"Pulling repository base"}
{"status"=>"Pulling image (ubuntu-quantl) from base", "progressDetail"=>{}, "id"=>"b750fe79269d"}
{"status"=>"Pulling image (ubuntu-quantl) from base, endpoint: https://cdn-registry-1.docker.io/v1/", "progressDetail"=>{}, "id"=>"b750fe79269d"}
{"status"=>"Pulling dependent layers", "progressDetail"=>{}, "id"=>"b750fe79269d"}
{"status"=>"Download complete", "progressDetail"=>{}, "id"=>"27cf78414709"}
{"status"=>"Download complete", "progressDetail"=>{}, "id"=>"b750fe79269d"}
{"status"=>"Download complete", "progressDetail"=>{}, "id"=>"b750fe79269d"}
答案 2 :(得分:0)
使用Docker v1.9我还有这个问题需要处理。 在Docker Github存储库中也发现了一个问题:Docker uses invalid JSON format in some API functions #16925
某位参与者建议使用Content-Type
HTTP标头,如下所示:application/json; boundary=NL
这不适合我。
然后,在使用我的自定义解析器时,发现了这个问题StackOverflow:How to handle a huge stream of JSON dictionaries?