Matthew Riley ([email protected])
This document summarizes the interactions between the Docker client and the Docker Hub during push
and pull
commands through version 1 of the registry API. It was compiled to aid in writing a compatible registry server implementation after the existing API documentation proved occasionally incomplete or inaccurate.
Behavior and code links were as of Docker v1.2.0.
docker {push|pull} H:P/R[:T]
Host, Port, Repository ([namespace/]image), Tag
GET H:P/v1/repositories/R/images
Authorization: Basic abc
X-Docker-Token: true
Response
X-Docker-Token: xyz
X-Docker-Endpoints: server1, server2
Split list on commas, then trim spaces from entries. (ref)
[{"checksum": "abc", "id": "123"}, ...]
JSON array of objects, one per image
GET server1/v1/repositories/R/tags
server is from X-Docker-Endpoints returned above
Authorization: Token xyz
token is from X-Docker-Token returned above
Response
{"tagname1": "image_id1", ...}
JSON object, one field per tag
Compute the union of the images list and the set of tagged images.
If no tag was specified, download all images with tags. Otherwise only download the one with a matching tag. Untagged images are ignored.
For each image:
GET server1/v1/images/IMAGEID/ancestry
Authorization: Token xyz
Response
["self_imageid", "parent_imageid", ..., "root_imageid"]
JSON array of image IDs as strings. Order is important! Starts with self, ends with root.
GET server1/v1/images/IMAGEID/json
Authorization: Token xyz
Response
X-Docker-Size: 123
Size of corresponding layer. Older Docker clients require this; newer ones allow it to be absent and substitute -1.
Response body is a JSON-formatted Image object.
GET server1/v1/images/IMAGEID/layer
Authorization: Token xyz
Response
Image contents
The Docker client will try to do a resumable transfer if the server returns "Accept-Ranges: bytes".
Prepare a list of all images in repository, with parents before children. From the returned list, create an array of ImgData values with
Id
andTag
set.
If an image is tagged multiple times then there is an (ID, Tag) pair for each tag. If an image is untagged, it is implicitly tagged as "". (The Tag field is omitted in JSON if it's empty, so what’s the point?)
Session.PushImageJSONIndex (validate = false)
PUT H:P/v1/repositories/R/
Content-Type: application/json
Authorization: Basic abc
X-Docker-Token: true
Request is a JSON array of ImgData values. Only ID (as "id") and Tag are set. In encoding, Tag is omitted if empty.
Response
X-Docker-Token: xyz
X-Docker-Endpoints: server1, server2
Manually handles arbitrarily many redirects (300 <= ResponseCode < 400). Each redirect sends the request as before. Server response code must be 200 or 201 for success.
For each image:
GET server1/v1/images/IMAGEID/json
Authorization: Token xyz
TagStore.pushImage (if the request to /json in LookupRemoteImage did not return 200)
PUT server1/v1/images/IMAGEID/json
Content-Type: application/json
Authorization: Token xyz
Body is JSON formatted Image object.
PUT server1/v1/images/IMAGEID/layer
Content-Type: application/octet-stream
Transfer-Encoding: chunked
Content-Length: -1
Authorization: Token xyz
Layer (.tar.gz) is read through TarSum.Read to create request body.
TarSum is frightening. Let's never use it for image authentication or identity.
PUT server1/v1/images/IMAGEID/checksum
Authorization: Token xyz
X-Docker-Checksum: tarsum+sha256:a0b1c2...
The TarSum calculated above.
X-Docker-Checksum-Payload: sha256:a0b1c2...
Payload checksum is "sha256:" + SHA256(json + "\n" + PAYLOAD), where PAYLOAD is the tar+gz’d layer that was actually sent as the request body.
For each of the image's tags:
PUT server1/v1/repositories/R/tags/T
Authentication: Token xyz
Content-Type: application/json
Request body is
"IMAGEID"
(with quotes).
Session.PushImageJSONIndex (validate = true)
PUT H:P/v1/repositories/R/images
Authentication: Basic abc
There doesn't seem to be a good reason here to use Basic authentication rather than the existing Token.
Request body is an array of ImgData values, same as before, except only images with a checksum set are included -- i.e. only the images uploaded this session.
Response
Server must return 204 on success.
The Docker client keeps a per-session set of cookies that is used and updated on each request. Cookies are not persisted across sessions.
The Docker Hub used to use these cookies for authentication, but stopped -- see the discussion in issue 330 for some context. As of this writing, quay.io still uses cookies for authentication. Since Docker Hub doesn't use cookies, there's some question as to whether they'll be tested or keep working in future Docker client versions. It may be more robust to return data in the authentication token.