docker registry v2 api

Docker Registry V2 api

本篇总结docker registry v2 api描述和使用docker-registry v2

API清单

method path Entity Description
GET /v2/ Base Check that the endpoint implements Docker Registry API V2.
GET /v2/<image>/tags/list Tags Fetch the tags under the repository identified by name.
GET /v2/<image>/manifests/<referevce> Manifest Fetch the manifest identified by nameand referencewhere referencecan be a tag or digest. A HEADrequest can also be issued to this endpoint to obtain resource information without receiving all data.
put /v2/<image>/manifests/<referevce> Manifest Put the manifest identified by nameand referencewhere referencecan be a tag or digest.
delete /v2/<image>/manifests/<reference> Manifest Delete the manifest identified by nameand reference. Note that a manifest can only be deleted by digest.
GET /v2/<image>/blobs/<digest> Blob Retrieve the blob from the registry identified bydigest. A HEADrequest can also be issued to this endpoint to obtain resource information without receiving all data.
DELETE /v2/<image>/blobs/<digest> Blob Delete the blob identified by nameand digest
POST /v2/<image>/blobs/uploads/ Initiate Blob Upload Initiate a resumable blob upload. If successful, an upload location will be provided to complete the upload. Optionally, if thedigest parameter is present, the request body will be used to complete the upload in a single request.
GET /v2/<image>/blobs/uploads/<uuid> Blob Upload Retrieve status of upload identified byuuid. The primary purpose of this endpoint is to resolve the current status of a resumable upload.
PATCH /v2/<image>/blobs/uploads/<uuid> Blob Upload Upload a chunk of data for the specified upload.
PUT /v2/<image>/blobs/uploads/<uuid> Blob Upload Complete the upload specified by uuid, optionally appending the body as the final chunk.
DELETE /v2/<image>/blobs/uploads/<uuid> Blob Upload Cancel outstanding upload processes, releasing associated resources. If this is not called, the unfinished uploads will eventually timeout.
GET /v2/_catalog Catalog Retrieve a sorted, json list of repositories available in the registry.

名词解释

  • repository name(存储库名词)

    存储库指在库中存储的镜像。/project/redis:latest

    • 语法:

      1. 经典存储库名称由2级路径构成,每级路径小于30个字符,V2的api不强制要求这样的格式。
      2. 每级路径名至少有一个小写字母或者数字,使用句号,破折号和下划线分割。更严格来说,它必须符合正则表达式:[a-z0-9]+[._-][a-z0-9]+)
      3. 多级路径用/分隔
      4. 存储库名称总长度(包括/)不能超过256个字符
  • digest(摘要)

    摘要是镜像每个层的唯一标示。虽然算法允许使用任意算法,但是为了兼容性应该使用sha256。例如sha256:6c3c624b58dbbcd3c0dd82b4c53f04194d1247c6eebdaab7c610cf7d66709b3b

    1. 生成摘要的伪代码

      import hashlib
      C = 'a small string'
      B = hashlib.sha256(C)
      D = 'sha256:' + B.hexdigest()
      

镜像pull过程

镜像由一个json清单和层叠文件组成,pull镜像的过程就是检索这两个组件的过程。拉去镜像的第一步就是获取清单,清单由下面几个字段组成: registry:5000/v2/redis/manifests/latest(获取redis:latest清单文件)

字段 描述
name 镜像名称
tag 镜像当前版本的tag
fsLayers 层描述列表(包括摘要)
signature 一个JWS签名,用来验证清单内容
当获取清单之后,客户端需要验证前面(signature),以确保名称和fsLayers层是有效的。确认后,客户端可以使用digest去下载各个fs层。在V2api中,层存储在blobs中已digest作为键值.

1. 首先拉取镜像清单(pulling an Image Manifest)
  
  $ HEAD /v2/<image/manifests/<reference>#检查镜像清单是否存在
  $ GET /v2/<image>/manifests/<reference>#拉取镜像清单
  提示:reference可是是tag或者是digest
  
2. 开始拉取每个层(pulling a Layer)
   $ GET /v2/<image>/blobs/<digest>
   提示:digest是镜像每个fsLayer层的唯一标识。存在于清单的fsLayers里面。

Push镜像过程

推送镜像和拉取镜像过程相反,先推各个层到registry仓库,然后上传清单.

  1. Pushing a Layer(上传层)

    上传层分为2步,第一步使用post请求在registry仓库启动上传服务,
    返回一个url,这个url用来上传数据和检查状态。

    • 首先Existing Layers(检查层是否存在)

      $ HEAD /v2/image/blobs/<digest>

      若返回200 OK 则表示存在,不用上传

    • 开始上传服务(Starting An Upload)

      $POST /v2/image/blobs/uploads/

      如果post请求返回202 accepted,一个url会在location字段返回.

           202 Accepted
           Location: /v2/\<image>/blobs/uploads/\<uuid>
           Range: bytes=0-<offset>
           Content-Length: 0
           Docker-Upload-UUID: <uuid> # 可以用来查看上传状态和实现断点续传
      
    • 开始上传层(Uploging the Layer)

      1. 上传进度(Upload Progress)

        $ GET /v2/<image>/blobs/uploads/<uuid>

        返回

           204 No Content
           Location: /v2/<name>/blobs/uploads/<uuid>
           Range: bytes=0-<offset>
           Docker-Upload-UUID: <uuid>
        
      2. 整块上传(Monolithic Upload)

      > PUT /v2/<name>/blobs/uploads/<uuid>?digest=\<digest>
      
      > Content-Length: \<size of layer>
      
      > Content-Type: application/octet-stream
      

<Layer Binary Data>

    3. 分块上传(Chunked Upload)
         
        > PATCH /v2/\<name>/blobs/uploads/\<uuid>
        
        > Content-Length: \<size of chunk>
        
        > Content-Range: \<start of range>-\<end of range>
        
        > Content-Type: application/octet-stream
        \<Layer Chunk Binary Data>
        
        如果服务器不接受这个块,则返回:
            
              416 Requested Range Not Satisfiable
              Location: /v2/<name>/blobs/uploads/<uuid>
              Range: 0-<last valid range>
              Content-Length: 0
              Docker-Upload-UUID: <uuid>
             
         成功则返回:
         
            202 Accepted
            Location: /v2/<name>/blobs/uploads/<uuid>
            Range: bytes=0-<offset>
            Content-Length: 0
            Docker-Upload-UUID: <uuid>
  • 上传完成(Completed Upload)

    分块上传在最后一块上传完毕后,需要提交一个上传完成的请求

       > PUT /v2/<name>/blob/uploads/<uuid>?digest=<digest>
       > Content-Length: <size of chunk>
       > Content-Range: <start of range>-<end of range>
       > Content-Type: application/octet-stream
       <Last Layer Chunk Binary Data>
    

    返回:

       201 Created
       Location: /v2/<name>/blobs/<digest>
       Content-Length: 0
       Docker-Content-Digest: <digest>
    
  • 取消上传(Canceling an Upload)

    这个请求执行后UUID将失效,当上传超时或者没有完成,客户端都应该发送这个请求。

    DELETE /v2/image/blobs/uploads/<uuid>

  • 交叉上传(Cross Repository Blob Mount)

    可以把客户端有访问权限的已有存储库中的层挂载到当前存储库中

    POST /v2/<name>/blobs/uploads/?mount=<digest>&from=<repository name>
    Content-Length: 0

    成功返回:

      201 Created
      Location: /v2/<name>/blobs/<digest>
      Content-Length: 0
      Docker-Content-Digest: <digest>
    

    失败返回:

      202 Accepted
      Location: /v2/<name>/blobs/uploads/<uuid>
      Range: bytes=0-<offset>
      Content-Length: 0
      Docker-Upload-UUID: <uuid>
    
  1. 删除层(Deleting a Layer)

    DELETE /v2/<image>/blobs/<digest>

    成功返回:

     202 Accepted
     Content-Length: None
    

    失败返回404错误

  2. 上传镜像清单(Pushing an Image Manifest)

    我们上传完镜像层之后,就开始上传镜像清单

     PUT /v2/<name>/manifests/<reference>
     Content-Type: <manifest media type>
     {
     "name": <name>,
     "tag": <tag>,
     "fsLayers": [
       {
          "blobSum": <digest>
       },
       ...
     ]
     ],
     "history": <v1 images>,
     "signature": <JWS>,
     ...
     }
    

    返回:

     如果清单中有层("blobSum":<digest>)是未知的,则返回
     {
      "errors:" [{
              "code": "BLOB_UNKNOWN",
              "message": "blob unknown to registry",
              "detail": {
                  "digest": <digest>
              }
          },
          ...
       ]
     }
    

检索功能

  1. 列出所有存储库(Listing Repositories)

    GET /v2/_catalog

    返回:

     200 OK
     Content-Type: application/json
     {
       "repositories": [
         <name>,
         ...
       ]
     }
    
  2. 列出部分存储库(Pagination)

    GET /v2/_catalog?n=<integer>

    Note: integer表示要列出库的个数

    返回:

     200 OK
     Content-Type: application/json
     Link: <<url>?n=<n from the request>&last=<last repository in response>>; rel="next"
     {
       "repositories": [
         <name>,
         ...
       ]
     }
    
  3. 列出镜像所有tags(Listing Image Tags)

    GET /v2/image/tags/list

    返回:

     200 OK
     Content-Type: application/json
     {
         "name": <name>,
         "tags": [
             <tag>,
             ...
         ]
     }
    
  4. 列出镜像部分tags(Pagination)

    GET /v2/image/tags/list?n=<integer>

    返回:

     200 OK
     Content-Type: application/json
     Link: <<url>?n=<n from the request>&last=<last tag value from previous response>>; rel="next"
     {
       "name": <name>,
       "tags": [
         <tag>,
         ...
       ]
     }
    
  5. 删除镜像(Deleting an Image)

    DELETE /v2/image/manifests/<reference>
    返回

     202 Accepted
     Content-Length: None
    

    失败返回404错误
    注意:默认情况下,registry不允许删除镜像操作,需要在启动registry时指定环境变量REGISTRY_STORAGE_DELETE_ENABLED=true,或者修改其配置文件即可。reference必须是digest,否则删除将失败。在registry2.3或更高版本删除清单时,必须在HEAD或GET获取清单以获取要删除的正确digest携带以下头:

Accept: application/vnd.docker.distribution.manifest.v2+json

6.待更新

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,236评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,867评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,715评论 0 340
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,899评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,895评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,733评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,085评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,722评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,025评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,696评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,816评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,447评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,057评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,254评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,204评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,561评论 2 343

推荐阅读更多精彩内容