如何使用Docker Registry API v2将镜像推送到Docker仓库

15

我正在编写一个Docker注册表API包装器,以从一个私有注册表中提取图像并将其推送到另一个注册表。

根据文档,首先需要提取图像的清单和层。按照提取镜像的步骤,我已成功下载了特定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. Completed Upload部分指出:

为了使上传被视为完成,客户端必须在上传终点提交一个带有摘要参数的PUT请求

但是,正如我所提到的,我正在使用Monolithic Upload,它使用PUT,与完成上传部分显示的请求相同。那么,通过进行单块上传,我也同时完成了上传吗?

问题

  1. 当我按照上述所有步骤操作时,上传摘要时收到BLOB_UNKNOWN错误,例如:

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

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

如果一个或多个层未知于注册表,则会返回BLOB_UNKNOWN错误。错误响应的详细信息字段将有一个摘要字段,用于标识缺失的blob。每个未知blob都会返回一个错误。响应格式如下:
这让我困惑的是:
1. 我正在推送摘要(也就是一个层),而不是清单,为什么会返回此错误?
2. 我预期这个blob是未知的,因为我正在向注册表中推送新的镜像。
目前我将使用docker客户端,但我没有在网上找到任何包装器示例来查看如何完成此操作。假定我缺少一些逻辑或误解了文档,但我不确定我哪里错了?

有点晚了,而且并不是一个解决方案:您是否考虑过使用Docker客户端(如您所说),但通过代理进行通信,以便您可以检查流量?因为客户端与v2注册表的通信是通过HTTP明文传输的,所以流量可以被人类读取和理解。 - Justin Tamblyn
你成功了吗?我遇到了同样的问题。 - Ayrton Werck
1个回答

4

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

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

我无法让仅使用POST的方法工作。在我的情况下,我使用它来在图层块之后和注册表清单之前上传图像清单。虽然POST看起来成功并返回202,但注册表上的调试日志显示它从暂存位置未被复制到数据存储区(与分块上传后发生的情况不同)。随后尝试上传清单,则失败并显示400和调试日志"blob unknown to registry"。

然而,我能够通过使用POST+PUT方法解决此问题。

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

尽管URI格式(/v2//blobs/uploads/)已经指定了Location头,但客户端应将其视为不透明的URL,并且不应尝试组装它。
单块上传只是一个具有单个块的分块上传。
遵循这两个说明,我使用POST创建了一个新的Location头(和UUID),附加了摘要值,并通过PUT将blob提交到修改后的位置来完成上传。
副笔:查看注册表调试日志,docker CLI在开始新的上传之前检查blob的存在性(并在完成上传后也会进行检查-假设是对状态代码的双重检查)。
更新:发现自己再次处理此问题,并想着向您更新我所发现的内容...

注册表仅支持在PATCHPUT操作期间处理响应正文;POST不调用copyFullPayload助手。此外,所有上传似乎都被视为单体式上传(即它们从单个请求正文流式传输 blob),因为尚未实现对Content-Range头的处理

顺带一提:我在进行重构期间,针对 V2 API 的测试覆盖率进行了此分析;这里是 POST+PUT 方法的工作示例。总体而言,我发现官方文档与当前实现在头部和状态码方面不同步。我已经在本地 V2 注册表和 DockerHub 上进行了测试,但没有在其他注册表(如 DTR、quay 或 MCR)上进行测试。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接