如何使用docker Registry API v2将映像推送到docker注册表

mdo*_*123 12 docker docker-registry docker-api

我正在编写一个docker注册表api包装器,用于从一个私有注册表中提取图像并将它们推送到另一个私有注册表.

首先根据文档我需要拉出清单和图层image:tag.在 Puling An Image之后,我已经成功下载了特定image:tag和清单的所有图层.

下面推的图像,我遵循的步骤:

  1. POST /v2/<name>/blobs/uploads/(获取UUID即Location标题)
  2. HEAD /v2/<name>/blobs/<digest> (检查注册表中是否已存在)
  3. PUT /v2/<name>/blobs/uploads/<uuid>?digest=<digest>(Monolithic Upload)

对我来说不清楚的是:

  1. UUID我推送的每个单独层是唯一的还是对所有层重用的(例如,我是否需要为每个层运行一个新的POST,UUID然后在尝试上传之前获取新的?).
  2. 完成上传部分指示

要使上传被视为完成,客户端必须在上传端点上使用摘要参数提交PUT请求

但是,正如我所提到的,我正在使用单片上传,它使用的是PUT与完成上传部分中显示的相同的请求.所以通过单片上传,我还可以同时完成上传吗?

问题

  1. 当我完成上述所有步骤时,我BLOB_UNKNOWN 在上传摘要时收到错误,例如

    {"errors:"[{"code":"BLOB_UNKNOWN","message":"blob unknown to registry","detail":{"digest":}},...]}

根据文档,在推送清单时会产生此错误,并且清单中的其中一个层未知:

如果注册表未知一个或多个图层,则返回BLOB_UNKNOWN错误.错误响应的详细信息字段将具有标识丢失的blob的摘要字段.每个未知blob都会返回一个错误.响应格式如下:

令我困惑的是

  1. 我正在推送一个摘要(也就是一个层)而不是清单,为什么这个错误会返回?
  2. 我希望blob是未知的,因为我正在将新图像推入注册表

现在我将使用docker客户端,但是我没有在线找到任何包装器示例,看看它是如何被拉出来的.据推测,我错过了一些逻辑或误解了文档,但我不确定我哪里出错了?

Ric*_*vis 4

哇,很高兴知道我不是唯一一个迷失在 V2 API 中的人......

我正在实现一个类似的库并遇到了同样的问题。根据我对文档的理解,有两种整体上传:单个交换POST变体(在文档底部提到)和两个交换POST+PUT变体(在文档顶部提到)。

我无法使仅 POST 方法起作用。就我而言,我使用它在层 blob 之后、注册表清单之前上传图像清单。虽然 POST 显示成功并返回 202,但注册表上的调试日志记录显示它从未从暂存位置复制到数据存储中(如分块上传后发生的情况)。随后尝试上传清单会失败,并显示 400,并调试日志记录“注册表未知的 blob”。

不过,我可以通过使用 POST+PUT 方法来解决这个问题。

对我来说,文档中的关键部分是:

尽管指定了 Location 标头的 URI 格式 (/v2//blobs/uploads/),但客户端应将其视为不透明的 url,并且永远不应该尝试组装它。

整体上传只是带有单个块的分块上传......

按照这两条指令,我使用 POST 创建了一个新的位置标头(和 UUID),附加了摘要值,并通过将 blob 放置到修改后的位置来完成上传。

旁注:查看注册表调试日志,docker CLI在开始新上传之前检查 Blob 是否存在(以及在完成上传之后 - 假设对状态代码进行双重检查)。

更新:发现自己再次致力于此,并想我会向您更新我的发现......

注册中心仅支持在PATCHPUT操作期间处理响应主体;copyFullPayload不会为POST调用助手。此外,所有上传似乎都被视为整体上传(从某种意义上说,它们从单个请求主体流式传输 blob),因为似乎没有实现Content-Range标头处理。

旁注:我在大修期间增加 V2 API 测试覆盖率的范围内进行了此分析;是 POST+PUT 方法的工作示例。总的来说,我发现官方文档在标头和状态代码方面与当前实现不同步。我已经针对本地 V2 注册表和 DockerHub 对此进行了测试,但没有针对其他注册表(例如 DTR、quay 或 MCR)进行了测试。