How to push an image to a docker registry using the docker Registry API v2 How to push an image to a docker registry using the docker Registry API v2 docker docker

How to push an image to a docker registry using the docker Registry API v2


Wow, it's nice to know I'm not the only one lost in the void with the V2 API ...

I'm implementing a similar library and ran across the same issue. From my understanding of the documentation there are two Monolithic uploads: The single exchange POST variant (mentioned at the bottom of the docs), and the two exchange POST + PUT variant (mentioned at the top of the docs).

I wasn't able to get the POST-only method working. In my case, I was using it to upload the image manifest after the layer blobs, and before the registry manifest. While the POST appears successful and returns 202, the debug logging on the registry shows that it's never replicated from the staging location into the data store (as happens after chunked uploads). The subsequent attempt to upload the manifest then fails with 400, and debug logging "blob unknown to registry".

I was, however, able to work around this issue by using the POST+PUT method.

The key sections in the docs for me were:

Though the URI format (/v2//blobs/uploads/) for the Location header is specified, clients should treat it as an opaque url and should never try to assemble it.

and

A monolithic upload is simply a chunked upload with a single chunk ...

Following those two instructions I created a new Location header (and UUID) using POST, appended the digest value, and completed the upload by PUTting the blob to the modified location.

Side note: Looking at the registry debug logs, the docker CLI checks the existence of the blobs before starting a new upload (and after completing the uploads too -- assuming as a double check on the status code).

Update: Found myself working on this again, and figured I'd update you on what I found ...

The registry only supports handling the response body during PATCH and PUT operations; the copyFullPayload helper is not invoked for POST. Additionally, all uploads appear to be treated as monolithic uploads (in the sense that they stream the blob from a single request body) as handling of the Content-Range header does not appear to be implemented.

Side Note: I conducted this analysis under the scope of increasing test coverage of the V2 API during an overhaul; here is a working example of the POST+PUT method. In general I've found the official documentation to be out-of-sync with the current implementation with regards to headers and status codes. I have tested this against a local V2 registry and DockerHub, but not against other registries such as DTR, quay, or MCR.