diff --git a/doc/SPEC.md b/doc/SPEC.md index c4a9ae9de..efe90bdaf 100644 --- a/doc/SPEC.md +++ b/doc/SPEC.md @@ -1,7 +1,13 @@ -# Proposal: JSON Registry API V2.1 +# Docker Registry API V2.1 + +> **Note**: This specification has been ported over from the proposal on +> docker/docker#9015. Much of the language in this document is still written +> in the proposal tense and needs to be converted. ## Abstract +> **TODO**: Merge this section into the overview/introduction. + The docker registry is a service to manage information about docker images and enable their distribution. While the current registry is usable, there are several problems with the architecture that have led to this proposal. For @@ -24,6 +30,8 @@ Furthermore, to bring docker registry in line with docker core, the registry is ## Scope +> **TODO**: Merge this section into the overview/introduction. + This proposal covers the URL layout and protocols of the Docker Registry V2 JSON API. This will affect the docker core registry API and the rewrite of docker-registry. @@ -42,6 +50,8 @@ support is complete. Please see the road map for details. ## Use Cases +> **TODO**: Merge this section into the overview/introduction. + For the most part, the use cases of the former registry API apply to the new version. Differentiating uses cases are covered below. @@ -71,24 +81,10 @@ If process A and B upload the same layer at the same time, both operations will proceed and the first to complete will be stored in the registry (Note: we may modify this to prevent dogpile with some locking mechanism). -### Access Control +## Overview -Company X would like to control which developers can push to which -repositories. By leveraging the URI format of the V2 registry, they can -control who is able to access which repository, who can pull images and who -can push layers. - -## Dependencies - -Initially, a V2 client will be developed in conjunction with the new registry -service to facilitate rich testing and verification. Once this is ready, the -new client will be used in docker to communicate with V2 registries. - -## Proposal - -This section covers proposed client flows and details of the proposed API -endpoints. All endpoints will be prefixed by the API version and the -repository name: +This section covers client flows and details of the API endpoints. All +endpoints will be prefixed by the API version and the repository name: /v2// @@ -97,9 +93,9 @@ repository, the URI prefix will be: /v2/library/ubuntu/ -This scheme will provide rich access control over various operations and -methods using the URI prefix and http methods that can be controlled in -variety of ways. +This scheme provides rich access control over various operations and methods +using the URI prefix and http methods that can be controlled in variety of +ways. Classically, repository names have always been two path components where each path component is less than 30 characters. The V2 registry API does not @@ -116,40 +112,19 @@ enforce this. The rules for a repository name are as follows: 256 characters. These name requirements _only_ apply to the registry API and should accept a -superset of what is supported by other docker community components. - -## API Methods - -A detailed list of methods and URIs are covered in the table below: - -|Method|Path|Entity|Description| --------|----|------|------------ -| GET | `/v2/` | Check | Check that the endpoint implements Docker Registry API V2. | -| GET | `/v2//tags/list` | Tags | Fetch the tags under the repository identified by `name`. | -| GET | `/v2//manifests/` | Manifest | Fetch the manifest identified by `name` and `tag`. | -| PUT | `/v2//manifests/` | Manifest | Put the manifest identified by `name` and `tag`. | -| DELETE | `/v2//manifests/` | Manifest | Delete the manifest identified by `name` and `tag`. | -| GET | `/v2//blobs/` | Blob | Retrieve the blob from the registry identified by `digest`. | -| HEAD | `/v2//blobs/` | Blob | Check if the blob is known to the registry. | -| POST | `/v2//blobs/uploads/` | Blob Upload | Initiate a resumable blob upload. If successful, an upload location will be provided to complete the upload. Optionally, if the `digest` parameter is present, the request body will be used to complete the upload in a single request. | -| GET | `/v2//blobs/uploads/` | Blob Upload | Retrieve status of upload identified by `uuid`. The primary purpose of this endpoint is to resolve the current status of a resumable upload. | -| HEAD | `/v2//blobs/uploads/` | Blob Upload | Retrieve status of upload identified by `uuid`. This is identical to the GET request. | -| PATCH | `/v2//blobs/uploads/` | Blob Upload | Upload a chunk of data for the specified upload. | -| PUT | `/v2//blobs/uploads/` | Blob Upload | Complete the upload specified by `uuid`, optionally appending the body as the final chunk. | -| DELETE | `/v2//blobs/uploads/` | Blob Upload | Cancel outstanding upload processes, releasing associated resources. If this is not called, the unfinished uploads will eventually timeout. | +superset of what is supported by other docker ecosystem components. All endpoints should support aggressive http caching, compression and range -headers, where appropriate. Details of each method are covered in the -following sections. +headers, where appropriate. The new API attempts to leverage HTTP semantics +where possible but may break from standards to implement targeted features. -The new API will attempt to leverage HTTP semantics where possible but may -break from standards to implement targeted features. +For detail on individual endpoints, please see the _Detail_ section. ### Errors Actionable failure conditions, covered in detail in their relevant sections, -will be reported as part of 4xx responses, in a json response body. One or -more errors will be returned in the following format: +are reported as part of 4xx responses, in a json response body. One or more +errors will be returned in the following format: { "errors:" [{ @@ -166,29 +141,14 @@ convention. The `message` field will be a human readable string. The optional `detail` field may contain arbitrary json data providing information the client can use to resolve the issue. -The error codes encountered via the API are enumerated in the following table: - -|Code|Message|Description|HTTPStatusCodes| ---------|--------|--------|-------- -|`UNKNOWN`|unknown error|Generic error returned when the error does not have an API classification.|Any| -|`DIGEST_INVALID`|provided digest did not match uploaded content|When a blob is uploaded, the registry will check that the content matches the digest provided by the client. The error may include a detail structure with the key "digest", including the invalid digest string. This error may also be returned when a manifest includes an invalid layer digest.|400, 404| -|`SIZE_INVALID`|provided length did not match content length|When a layer is uploaded, the provided size will be checked against the uploaded content. If they do not match, this error will be returned.|400| -|`NAME_INVALID`|manifest name did not match URI|During a manifest upload, if the name in the manifest does not match the uri name, this error will be returned.|400, 404| -|`TAG_INVALID`|manifest tag did not match URI|During a manifest upload, if the tag in the manifest does not match the uri tag, this error will be returned.|400, 404| -|`NAME_UNKNOWN`|repository name not known to registry|This is returned if the name used during an operation is unknown to the registry.|404| -|`MANIFEST_UNKNOWN`|manifest unknown|This error is returned when the manifest, identified by name and tag is unknown to the repository.|404| -|`MANIFEST_INVALID`|manifest invalid|During upload, manifests undergo several checks ensuring validity. If those checks fail, this error may be returned, unless a more specific error is included. The detail will contain information the failed validation.|400| -|`MANIFEST_UNVERIFIED`|manifest failed signature verification|During manifest upload, if the manifest fails signature verification, this error will be returned.|400| -|`BLOB_UNKNOWN`|blob unknown to registry|This error may be returned when a blob is unknown to the registry in a specified repository. This can be returned with a standard get or if a manifest references an unknown layer during upload.|400, 404| -|`BLOB_UPLOAD_UNKNOWN`|blob upload unknown to registry|If a blob upload has been cancelled or was never started, this error code may be returned.|404| - - While the client can take action on certain error codes, the registry may add new error codes over time. All client implementations should treat unknown error codes as `UNKNOWN`, allowing future error codes to be added without breaking API compatibility. For the purposes of the specification error codes will only be added and never removed. +For a complete account of all error codes, please see the _Detail_ section. + ### API Version Check A minimal endpoint, mounted at `/v2/` will provide version support information @@ -233,8 +193,6 @@ the names and layers are valid. Once confirmed, the client will then use the tarsums to download the individual layers. Layers are stored in as blobs in the V2 registry API, keyed by their tarsum digest. -The API details follow. - #### Pulling an Image Manifest The image manifest can be fetched with the following url: @@ -465,8 +423,8 @@ range" and upload the subsequent chunk. A 416 will be returned under the following conditions: - Invalid Content-Range header format -- Out of order chunk: the range of the next chunk must start after the "last - valid range" from the last response. +- Out of order chunk: the range of the next chunk must start immediately after + the "last valid range" from the previous response. When a chunk is accepted as part of the upload, a `202 Accepted` response will be returned, including a `Range` header with the current upload status: @@ -563,14 +521,6 @@ the problem. After receiving a 4xx response (except 416, as called out above), the upload will be considered failed and the client should take appropriate action. -The following table covers the various error conditions that may be returned -after completing a layer upload: - - Code | Message | ------------------|--------------------------------------------------| -DIGEST_INVALID | provided digest did not match uploaded content | -SIZE_INVALID | provided size did not match content size | - Note that the upload url will not be available forever. If the upload uuid is unknown to the registry, a `404 Not Found` response will be returned and the client must restart the upload process. @@ -578,7 +528,7 @@ client must restart the upload process. #### Pushing an Image Manifest Once all of the layers for an image are uploaded, the client can upload the -image manifest. An image can be pushed using the following request formats: +image manifest. An image can be pushed using the following request format: PUT /v2//manifests/ @@ -601,30 +551,20 @@ The `name` and `tag` fields of the response body must match those specified in the URL. If there is a problem with pushing the manifest, a relevant 4xx response will -be returned with a JSON error message. The following table covers the various -error conditions and their corresponding codes: +be returned with a JSON error message. Please see the _PUT Manifest section +for details on possible error codes that may be returned. - Code | Message | ----------------------|--------------------------------------------------| -NAME_INVALID | Manifest name did not match URI | -TAG_INVALID | Manifest tag did not match URI | -MANIFEST_INVALID | Returned when an invalid manifest is received | -MANIFEST_UNVERIFIED | Manifest failed signature validation | -BLOB_UNKNOWN | Referenced layer not available | - -For the `UNKNOWN_LAYER` error, the `detail` field of the error response will -have an "unknown" field with information about the missing layer. For now, -that will just be the tarsum. There will be an error returned for each unknown -blob. The response format will be as follows: +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, which will be a tarsum. An error is returned for +each unknown blob. The response format is as follows: { "errors:" [{ - "code": "UNKNOWN_LAYER", - "message": "Referenced layer not available", + "code": "BLOB_UNKNOWN", + "message": "blob unknown to registry", "detail": { - "unknown": { - "blobSum": - } + "digest": } }, ... @@ -671,21 +611,1020 @@ will be issued: If the image had already been deleted or did not exist, a `404 Not Found` response will be issued instead. -## Roadmap +## Detail + +> **Note**: This section is still under construction. For the purposes of +> implementation, if any details below differ from the described request flows +> above, the section below should be corrected. When they match, this note +> should be removed. + +The behavior of the endpoints are covered in detail in this section, organized +by route and entity. All aspects of the request and responses are covered, +including headers, parameters and body formats. Examples of requests and their +corresponding responses, with success and failure, are enumerated. + +> **Note**: The sections on endpoint detail are arranged with an example +> request, a description of the request, followed by information about that +> request. + +A list of methods and URIs are covered in the table below: + +|Method|Path|Entity|Description| +-------|----|------|------------ +| GET | `/v2/` | Base | Check that the endpoint implements Docker Registry API V2. | +| GET | `/v2//tags/list` | Tags | Fetch the tags under the repository identified by `name`. | +| GET | `/v2//manifests/` | Manifest | Fetch the manifest identified by `name` and `tag`. | +| PUT | `/v2//manifests/` | Manifest | Put the manifest identified by `name` and `tag`. | +| DELETE | `/v2//manifests/` | Manifest | Delete the manifest identified by `name` and `tag`. | +| GET | `/v2//blobs/` | Blob | Retrieve the blob from the registry identified by `digest`. | +| HEAD | `/v2//blobs/` | Blob | Check if the blob is known to the registry. | +| POST | `/v2//blobs/uploads/` | Intiate Blob Upload | Initiate a resumable blob upload. If successful, an upload location will be provided to complete the upload. Optionally, if the `digest` parameter is present, the request body will be used to complete the upload in a single request. | +| GET | `/v2//blobs/uploads/` | Blob Upload | Retrieve status of upload identified by `uuid`. The primary purpose of this endpoint is to resolve the current status of a resumable upload. | +| HEAD | `/v2//blobs/uploads/` | Blob Upload | Retrieve status of upload identified by `uuid`. This is identical to the GET request. | +| PATCH | `/v2//blobs/uploads/` | Blob Upload | Upload a chunk of data for the specified upload. | +| PUT | `/v2//blobs/uploads/` | Blob Upload | Complete the upload specified by `uuid`, optionally appending the body as the final chunk. | +| DELETE | `/v2//blobs/uploads/` | Blob Upload | Cancel outstanding upload processes, releasing associated resources. If this is not called, the unfinished uploads will eventually timeout. | + + +The detail for each endpoint is covered in the following sections. + +### Errors + +The error codes encountered via the API are enumerated in the following table: + +|Code|Message|Description| +-------|----|------|------------ + `UNKNOWN` | unknown error | Generic error returned when the error does not have an API classification. + `DIGEST_INVALID` | provided digest did not match uploaded content | When a blob is uploaded, the registry will check that the content matches the digest provided by the client. The error may include a detail structure with the key "digest", including the invalid digest string. This error may also be returned when a manifest includes an invalid layer digest. + `SIZE_INVALID` | provided length did not match content length | When a layer is uploaded, the provided size will be checked against the uploaded content. If they do not match, this error will be returned. + `NAME_INVALID` | manifest name did not match URI | During a manifest upload, if the name in the manifest does not match the uri name, this error will be returned. + `TAG_INVALID` | manifest tag did not match URI | During a manifest upload, if the tag in the manifest does not match the uri tag, this error will be returned. + `NAME_UNKNOWN` | repository name not known to registry | This is returned if the name used during an operation is unknown to the registry. + `MANIFEST_UNKNOWN` | manifest unknown | This error is returned when the manifest, identified by name and tag is unknown to the repository. + `MANIFEST_INVALID` | manifest invalid | During upload, manifests undergo several checks ensuring validity. If those checks fail, this error may be returned, unless a more specific error is included. The detail will contain information the failed validation. + `MANIFEST_UNVERIFIED` | manifest failed signature verification | During manifest upload, if the manifest fails signature verification, this error will be returned. + `BLOB_UNKNOWN` | blob unknown to registry | This error may be returned when a blob is unknown to the registry in a specified repository. This can be returned with a standard get or if a manifest references an unknown layer during upload. + `BLOB_UPLOAD_UNKNOWN` | blob upload unknown to registry | If a blob upload has been cancelled or was never started, this error code may be returned. + + + +### Base + +Base V2 API route. Typically, this can be used for lightweight version checks and to validate registry authorization. + + + +#### GET Base + +Check that the endpoint implements Docker Registry API V2. + + +##### + +``` +GET /v2/ +Authorization: +``` + + + + +The following parameters should be specified on the request: + +|Name|Kind|Description| +|----|----|-----------| +|`Authorization`|header|rfc7235 compliant authorization header.| + + + + +###### On Success: OK + +``` +200 OK +``` + +The API implements V2 protocol and is accessible. + + + +###### On Failure: Unauthorized + +``` +401 Unauthorized +WWW-Authenticate: realm="", ..." +``` + +The client is not authorized to access the registry. + +The following headers will be returned on the response: + +|Name|Description| +|----|-----------| +|`WWW-Authenticate`|An RFC7235 compliant authentication challenge header.| + + + +###### On Failure: Not Found + +``` +404 Not Found +``` + +The registry does not implement the V2 API. + + + + + +### Tags + +Retrieve information about tags. + + + +#### GET Tags + +Fetch the tags under the repository identified by `name`. + + +##### + +``` +GET /v2//tags/list +``` + + + + +The following parameters should be specified on the request: + +|Name|Kind|Description| +|----|----|-----------| +|`name`|path|Name of the target repository.| + + + + +###### On Success: OK + +``` +200 OK +Content-Type: application/json + +{ + "name": , + "tags": [ + , + ... + ] +} +``` + +A list of tags for the named repository. + + + +###### On Failure: Not Found + +``` +404 Not Found +``` + +The repository is not known to the registry. + + + +###### On Failure: Unauthorized + +``` +401 Unauthorized +``` + +The client doesn't have access to repository. + + + + + +### Manifest + +Create, update and retrieve manifests. + + + +#### GET Manifest + +Fetch the manifest identified by `name` and `tag`. + + +##### + +``` +GET /v2//manifests/ +``` + + + + +The following parameters should be specified on the request: + +|Name|Kind|Description| +|----|----|-----------| +|`name`|path|Name of the target repository.| +|`tag`|path|Tag of the target manifiest.| + + + + +###### On Success: OK + +``` +200 OK +Content-Type: application/json + +{ + "name": , + "tag": , + "fsLayers": [ + { + "blobSum": + }, + ... + ] + ], + "history": , + "signature": +} +``` + +The manifest idenfied by `name` and `tag`. + + + +###### On Failure: Bad Request + +``` +400 Bad Request +Content-Type: application/json + +{ + "errors:" [{ + "code": , + "message": "", + "detail": ... + }, + ... + ] +} +``` + +The name or tag was invalid. + + + +The error codes that may be included in the response body are enumerated below: + +|Code|Message|Description| +-------|----|------|------------ +| `NAME_INVALID` | manifest name did not match URI | During a manifest upload, if the name in the manifest does not match the uri name, this error will be returned. | +| `TAG_INVALID` | manifest tag did not match URI | During a manifest upload, if the tag in the manifest does not match the uri tag, this error will be returned. | + + + +###### On Failure: Not Found + +``` +404 Not Found +Content-Type: application/json + +{ + "errors:" [{ + "code": , + "message": "", + "detail": ... + }, + ... + ] +} +``` + +The named manifest is not known to the registry. + + + +The error codes that may be included in the response body are enumerated below: + +|Code|Message|Description| +-------|----|------|------------ +| `NAME_UNKNOWN` | repository name not known to registry | This is returned if the name used during an operation is unknown to the registry. | +| `MANIFEST_UNKNOWN` | manifest unknown | This error is returned when the manifest, identified by name and tag is unknown to the repository. | + + + + +#### PUT Manifest + +Put the manifest identified by `name` and `tag`. + + +##### + +``` +PUT /v2//manifests/ +Authorization: +Content-Type: application/json + +{ + "name": , + "tag": , + "fsLayers": [ + { + "blobSum": + }, + ... + ] + ], + "history": , + "signature": +} +``` + + + + +The following parameters should be specified on the request: + +|Name|Kind|Description| +|----|----|-----------| +|`Authorization`|header|rfc7235 compliant authorization header.| +|`name`|path|Name of the target repository.| +|`tag`|path|Tag of the target manifiest.| + + + + +###### On Success: Accepted + +``` +202 Accepted +``` + + + + + +###### On Failure: Bad Request + +``` +400 Bad Request +``` + + + + + +The error codes that may be included in the response body are enumerated below: + +|Code|Message|Description| +-------|----|------|------------ +| `NAME_INVALID` | manifest name did not match URI | During a manifest upload, if the name in the manifest does not match the uri name, this error will be returned. | +| `TAG_INVALID` | manifest tag did not match URI | During a manifest upload, if the tag in the manifest does not match the uri tag, this error will be returned. | +| `MANIFEST_INVALID` | manifest invalid | During upload, manifests undergo several checks ensuring validity. If those checks fail, this error may be returned, unless a more specific error is included. The detail will contain information the failed validation. | +| `MANIFEST_UNVERIFIED` | manifest failed signature verification | During manifest upload, if the manifest fails signature verification, this error will be returned. | +| `BLOB_UNKNOWN` | blob unknown to registry | This error may be returned when a blob is unknown to the registry in a specified repository. This can be returned with a standard get or if a manifest references an unknown layer during upload. | + + + +###### On Failure: Bad Request + +``` +400 Bad Request +Content-Type: application/json + +{ + "errors:" [{ + "code": "BLOB_UNKNOWN", + "message": "blob unknown to registry", + "detail": { + "digest": + } + }, + ... + ] +} +``` + +One or more layers may be missing during a manifest upload. If so, the missing layers will be enumerated in the error response. + + + +The error codes that may be included in the response body are enumerated below: + +|Code|Message|Description| +-------|----|------|------------ +| `BLOB_UNKNOWN` | blob unknown to registry | This error may be returned when a blob is unknown to the registry in a specified repository. This can be returned with a standard get or if a manifest references an unknown layer during upload. | + + + +###### On Failure: Unauthorized + +``` +401 Unauthorized +WWW-Authenticate: realm="", ..." +``` + + + +The following headers will be returned on the response: + +|Name|Description| +|----|-----------| +|`WWW-Authenticate`|An RFC7235 compliant authentication challenge header.| + + + + +#### DELETE Manifest + +Delete the manifest identified by `name` and `tag`. + + +##### + +``` +DELETE /v2//manifests/ +Authorization: +``` + + + + +The following parameters should be specified on the request: + +|Name|Kind|Description| +|----|----|-----------| +|`Authorization`|header|rfc7235 compliant authorization header.| +|`name`|path|Name of the target repository.| +|`tag`|path|Tag of the target manifiest.| + + + + +###### On Success: Accepted + +``` +202 Accepted +``` + + + + + +###### On Failure: Bad Request + +``` +400 Bad Request +``` + + + + + +The error codes that may be included in the response body are enumerated below: + +|Code|Message|Description| +-------|----|------|------------ +| `NAME_INVALID` | manifest name did not match URI | During a manifest upload, if the name in the manifest does not match the uri name, this error will be returned. | +| `TAG_INVALID` | manifest tag did not match URI | During a manifest upload, if the tag in the manifest does not match the uri tag, this error will be returned. | + + + +###### On Failure: Unauthorized + +``` +401 Unauthorized +WWW-Authenticate: realm="", ..." +``` + + + +The following headers will be returned on the response: + +|Name|Description| +|----|-----------| +|`WWW-Authenticate`|An RFC7235 compliant authentication challenge header.| + + + +###### On Failure: Not Found + +``` +404 Not Found +``` + + + + + +The error codes that may be included in the response body are enumerated below: + +|Code|Message|Description| +-------|----|------|------------ +| `NAME_UNKNOWN` | repository name not known to registry | This is returned if the name used during an operation is unknown to the registry. | +| `MANIFEST_UNKNOWN` | manifest unknown | This error is returned when the manifest, identified by name and tag is unknown to the repository. | + + + + + +### Blob + +Fetch the blob identified by `name` and `digest`. Used to fetch layers by tarsum digest. + + + +#### GET Blob + +Retrieve the blob from the registry identified by `digest`. + + +##### + +``` +GET /v2//blobs/ +``` + + + + +The following parameters should be specified on the request: + +|Name|Kind|Description| +|----|----|-----------| +|`name`|path|Name of the target repository.| +|`digest`|path|Digest of desired blob.| + + + + +###### On Success: OK + +``` +200 OK +Content-Type: application/octet-stream + + +``` + +The blob identified by `digest` is available. The blob content will be present in the body of the request. +###### On Success: Temporary Redirect + +``` +307 Temporary Redirect +Location: +``` + +The blob identified by `digest` is available at the provided location. +The following headers will be returned on the response: + +|Name|Description| +|----|-----------| +|`Location`|The location where the layer should be accessible.| + + + + +###### On Failure: Bad Request + +``` +400 Bad Request +``` + + + + + +The error codes that may be included in the response body are enumerated below: + +|Code|Message|Description| +-------|----|------|------------ +| `NAME_INVALID` | manifest name did not match URI | During a manifest upload, if the name in the manifest does not match the uri name, this error will be returned. | +| `DIGEST_INVALID` | provided digest did not match uploaded content | When a blob is uploaded, the registry will check that the content matches the digest provided by the client. The error may include a detail structure with the key "digest", including the invalid digest string. This error may also be returned when a manifest includes an invalid layer digest. | + + + +###### On Failure: Unauthorized + +``` +401 Unauthorized +``` + + + + + +###### On Failure: Not Found + +``` +404 Not Found +``` + + + + + +The error codes that may be included in the response body are enumerated below: + +|Code|Message|Description| +-------|----|------|------------ +| `NAME_UNKNOWN` | repository name not known to registry | This is returned if the name used during an operation is unknown to the registry. | +| `BLOB_UNKNOWN` | blob unknown to registry | This error may be returned when a blob is unknown to the registry in a specified repository. This can be returned with a standard get or if a manifest references an unknown layer during upload. | + + + + +#### HEAD Blob + +Check if the blob is known to the registry. + + +##### + +``` +HEAD /v2//blobs/ +``` + + + + +The following parameters should be specified on the request: + +|Name|Kind|Description| +|----|----|-----------| +|`name`|path|Name of the target repository.| +|`digest`|path|Digest of desired blob.| + + + + + + + +### Intiate Blob Upload + +Initiate a blob upload. This endpoint can be used to create resumable uploads or monolithic uploads. + + + +#### POST Intiate Blob Upload + +Initiate a resumable blob upload. If successful, an upload location will be provided to complete the upload. Optionally, if the `digest` parameter is present, the request body will be used to complete the upload in a single request. + + +##### Initiate Monolithic Blob Upload + +``` +POST /v2//blobs/uploads/?digest= +Authorization: +Content-Length: +Content-Type: application/octect-stream + + +``` + +Upload a blob identified by the `digest` parameter in single request. This upload will not be resumable unless a recoverable error is returned. + + +The following parameters should be specified on the request: + +|Name|Kind|Description| +|----|----|-----------| +|`Authorization`|header|rfc7235 compliant authorization header.| +|`Content-Length`|header|| +|`name`|path|Name of the target repository.| +|`digest`|query|Digest of uploaded blob. If present, the upload will be completed, in a single request, with contents of the request body as the resulting blob.| + + + + +###### On Success: Created + +``` +201 Created +Location: +Content-Length: 0 +``` + + +The following headers will be returned on the response: + +|Name|Description| +|----|-----------| +|`Location`|| +|`Content-Length`|The `Content-Length` header must be zero and the body must be empty.| + + + + +###### On Failure: Invalid Name or Digest + +``` +400 Bad Request +``` + + + + + +The error codes that may be included in the response body are enumerated below: + +|Code|Message|Description| +-------|----|------|------------ +| `DIGEST_INVALID` | provided digest did not match uploaded content | When a blob is uploaded, the registry will check that the content matches the digest provided by the client. The error may include a detail structure with the key "digest", including the invalid digest string. This error may also be returned when a manifest includes an invalid layer digest. | +| `NAME_INVALID` | manifest name did not match URI | During a manifest upload, if the name in the manifest does not match the uri name, this error will be returned. | + + + +###### On Failure: Unauthorized + +``` +401 Unauthorized +WWW-Authenticate: realm="", ..." +``` + + + +The following headers will be returned on the response: + +|Name|Description| +|----|-----------| +|`WWW-Authenticate`|An RFC7235 compliant authentication challenge header.| + + + +The error codes that may be included in the response body are enumerated below: + +|Code|Message|Description| +-------|----|------|------------ +| `DIGEST_INVALID` | provided digest did not match uploaded content | When a blob is uploaded, the registry will check that the content matches the digest provided by the client. The error may include a detail structure with the key "digest", including the invalid digest string. This error may also be returned when a manifest includes an invalid layer digest. | +| `NAME_INVALID` | manifest name did not match URI | During a manifest upload, if the name in the manifest does not match the uri name, this error will be returned. | + + + +##### Initiate Resumable Blob Upload + +``` +POST /v2//blobs/uploads/ +Authorization: +Content-Length: 0 +``` + +Initiate a resumable blob upload with an empty request body. + + +The following parameters should be specified on the request: + +|Name|Kind|Description| +|----|----|-----------| +|`Authorization`|header|rfc7235 compliant authorization header.| +|`Content-Length`|header|The `Content-Length` header must be zero and the body must be empty.| +|`name`|path|Name of the target repository.| + + + + +###### On Success: Accepted + +``` +202 Accepted +Content-Length: 0 +Location: /v2//blobs/uploads/ +Range: 0-0 +``` + +The upload has been created. The `Location` header must be used to complete the upload. The response should identical to a `GET` request on the contents of the returned `Location` header. +The following headers will be returned on the response: + +|Name|Description| +|----|-----------| +|`Content-Length`|The `Content-Length` header must be zero and the body must be empty.| +|`Location`|The location of the created upload. Clients should use the contents verbatim to complete the upload, adding parameters where required.| +|`Range`|Range header indicating the progress of the upload. When starting an upload, it will return an empty range, since no content has been received.| + + + + + +### Blob Upload + +Interact with blob uploads. Clients should never assemble URLs for this endpoint and should only take it through the `Location` header on related API requests. + + + +#### GET Blob Upload + +Retrieve status of upload identified by `uuid`. The primary purpose of this endpoint is to resolve the current status of a resumable upload. + + +##### + +``` +GET /v2//blobs/uploads/ +``` + +Retrieve the progress of the current upload, as reported by the `Range` header. + + +The following parameters should be specified on the request: + +|Name|Kind|Description| +|----|----|-----------| +|`name`|path|Name of the target repository.| +|`uuid`|path|A uuid identifying the upload. This field can accept almost anything.| + + + + +###### On Success: No Content + +``` +204 No Content +Range: 0- +``` + + +The following headers will be returned on the response: + +|Name|Description| +|----|-----------| +|`Range`|Range indicating the current progress of the upload.| + + + + +#### HEAD Blob Upload + +Retrieve status of upload identified by `uuid`. This is identical to the GET request. + + +##### + +``` +HEAD /v2//blobs/uploads/ +``` + +Retrieve the progress of the current upload, as reported by the `Range` header. + + +The following parameters should be specified on the request: + +|Name|Kind|Description| +|----|----|-----------| +|`name`|path|Name of the target repository.| +|`uuid`|path|A uuid identifying the upload. This field can accept almost anything.| + + + + +###### On Success: No Content + +``` +204 No Content +Range: 0- +``` + + +The following headers will be returned on the response: + +|Name|Description| +|----|-----------| +|`Range`|Range indicating the current progress of the upload.| + + + + +#### PATCH Blob Upload + +Upload a chunk of data for the specified upload. + + +##### + +``` +PATCH /v2//blobs/uploads/ +Content-Range: - +Content-Length: +Content-Type: application/octet-stream + + +``` + +Upload a chunk of data to specified upload without completing the upload. + + +The following parameters should be specified on the request: + +|Name|Kind|Description| +|----|----|-----------| +|`Content-Range`|header|Range of bytes identifying the desired block of content represented by the body. Start must the end offset retrieved via status check plus one. Note that this is a non-standard use of the `Content-Range` header.| +|`Content-Length`|header|Length of the chunk being uploaded, corresponding the length of the request body.| +|`name`|path|Name of the target repository.| +|`uuid`|path|A uuid identifying the upload. This field can accept almost anything.| + + + + +###### On Success: No Content + +``` +204 No Content +Range: 0- +Content-Length: 0 +``` + + +The following headers will be returned on the response: + +|Name|Description| +|----|-----------| +|`Range`|Range indicating the current progress of the upload.| +|`Content-Length`|The `Content-Length` header must be zero and the body must be empty.| + + + + +#### PUT Blob Upload + +Complete the upload specified by `uuid`, optionally appending the body as the final chunk. + + +##### + +``` +PUT /v2//blobs/uploads/?digest= +``` + +Upload the _final_ chunk of data. + + +The following parameters should be specified on the request: + +|Name|Kind|Description| +|----|----|-----------| +|`name`|path|Name of the target repository.| +|`uuid`|path|A uuid identifying the upload. This field can accept almost anything.| +|`digest`|query|Digest of uploaded blob.| + + + + +###### On Success: No Content + +``` +204 No Content +Content-Range: - +Content-Length: +Content-Type: application/octet-stream + + +``` + + +The following headers will be returned on the response: + +|Name|Description| +|----|-----------| +|`Content-Range`|Range of bytes identifying the desired block of content represented by the body. Start must match the end of offset retrieved via status check. Note that this is a non-standard use of the `Content-Range` header.| +|`Content-Length`|Length of the chunk being uploaded, corresponding the length of the request body.| + + + + +#### DELETE Blob Upload + +Cancel outstanding upload processes, releasing associated resources. If this is not called, the unfinished uploads will eventually timeout. + + +##### + +``` +DELETE /v2//blobs/uploads/ +``` + +Cancel the upload specified by `uuid`. + + +The following parameters should be specified on the request: + +|Name|Kind|Description| +|----|----|-----------| +|`name`|path|Name of the target repository.| +|`uuid`|path|A uuid identifying the upload. This field can accept almost anything.| + + + + -- [X] Write Registry REST API V2 proposal - - [ ] Solicit feedback -- [ ] Implement V2 API server - - [X] Basic Layer API - - [X] Basic Image API - - [ ] Resumable upload support -- [ ] Implement V2 API client -- [ ] Implement API compliance tests -- [ ] Port docker core to use client from registry project for v2 pushes -## Reviewers -- @dmp42 -- @dmcgowan -- @jlhawn -- Docker Community \ No newline at end of file