I'm a writing a docker registry API wrapper to pull images from one private registry and push them to another.
Based on the documentation first I need to pull the manifest and the layers for an image:tag. Following Puling An Image I've successfully downloaded all the layers for a particular image:tag and the manifest.
Following Pushing An Image I've followed the steps:
POST /v2/<name>/blobs/uploads/(to get the UUID i.e.Locationheader)HEAD /v2/<name>/blobs/<digest>(check to see if it already exists in the registry)PUT /v2/<name>/blobs/uploads/<uuid>?digest=<digest>(Monolithic Upload)
What's not clear to me are the following:
- Is the
UUIDunique to each individual layer I push or is that reused for all layers (e.g. Do I need to run a new POST for each layer an get a newUUIDbefore I attempt to upload it?). - The Completed Upload section indicates
For an upload to be considered complete, the client must submit a PUT request on the upload endpoint with a digest parameter
However, as mentioned I'm using the Monolithic Upload which uses a PUT and would be the same request as what shows in the Completed Upload section. So by doing a monolithic upload am I also completing the upload at the same time?
Problem
When I go through all the steps above I receive the
BLOB_UNKNOWNerror when uploading a digest, e.g.{ "errors:" [{ "code": "BLOB_UNKNOWN", "message": "blob unknown to registry", "detail": { "digest": } }, ... ] }
According to the docs this error is produced when pushing a manifest and one of the layers in the manifest are unknown:
If one or more layers are unknown to the registry, BLOB_UNKNOWN errors are returned. The detail field of the error response will have a digest field identifying the missing blob. An error is returned for each unknown blob. The response format is as follows:
What confuses me about this is
- I'm pushing a digest (aka a layer) not the manifest so why is this error returning?
- I would expect the blob to be unknown because I'm pushing a new image into the registry
For now I'm going to use the docker client, but I haven't found any wrapper examples on-line to see how this is pulled off. Presumably I'm missing some logic or misunderstanding the docs, but I'm not sure where I'm going wrong?