使用API​​(2.5.1)

时间:2016-11-23 17:17:30

标签: api curl docker docker-registry

嗨,我正在尝试使用API​​将docker容器上传到私有docker注册表。

使用docker命令似乎一切正常:

docker pull ubuntu:16.04
docker tag ubuntu:16.04 <PRIVATE-REGISTRY-IP>:5000/ubuntu/16.04
docker push <PRIVATE-REGISTRY-IP>:5000/ubuntu/16.04

我正在尝试使用API​​上传相同的图片,我已经完成了:

  • 使用docker save ubuntu:16.04 -o ubuntu.tar
  • 导出容器
  • 解压缩容器文件tar xf ubuntu.tar
  • 使用curl上传所有图层
  • 使用curl上传清单

好的,阅读the doc,这些图层必须是PUT,每个图层都使用sha256sum <LAYER-FILE>获取摘要,并且在完成后,清单也应该PUT到注册表中

卷曲电话详情:)

curl -XPOST -H 'accept: application/json' http://<PRIVATE-REGISTRY-IP>:5000/v2/ubuntu/blobs/uploads/
response headers: {"Docker-Distribution-Api-Version":["registry/2.0"],"Docker-Upload-Uuid":["318d5752-b10b-49da-9ebf-5891b679a805"],"X-Content-Type-Options":["nosniff"],"Range":["0-0"],"Content-Length":["0"],"Date":["Wed, 23 Nov 2016 16:05:53 GMT"],"Content-Type":["text/plain; charset\u003dutf-8"],"Location":["http://<PRIVATE-REGISTRY-IP>:5000/v2/ubuntu/blobs/uploads/318d5752-b10b-49da-9ebf-5891b679a805?_state\u003dv2nk-ATsPGQKJatyjUQTSJwl2BlQywrqeCkVTzQj0uh7Ik5hbWUiOiJ0ZXN0MDEiLCJVVUlEIjoiMzE4ZDU3NTItYjEwYi00OWRhLTllYmYtNTg5MWI2NzlhODA1IiwiT2Zmc2V0IjowLCJTdGFydGVkQXQiOiIyMDE2LTExLTIzVDE2OjA1OjUzLjE1Njk5NzUxM1oifQ%3D%3D"]}
DIGEST=$(sha256sum /home/user/container/ubuntu/3e1722599d1d5331b610200b6b41f895759e312ff1f14e009bee2f52f962b69f/layer.tar)
curl -XPUT -H 'accept: application/json' -d @/home/user/container/ubuntu/3e1722599d1d5331b610200b6b41f895759e312ff1f14e009bee2f52f962b69f/layer.tar http://<PRIVATE-REGISTRY-IP>:5000/v2/ubuntu/blobs/uploads/318d5752-b10b-49da-9ebf-5891b679a805?_state=v2nk-ATsPGQKJatyjUQTSJwl2BlQywrqeCkVTzQj0uh7Ik5hbWUiOiJ0ZXN0MDEiLCJVVUlEIjoiMzE4ZDU3NTItYjEwYi00OWRhLTllYmYtNTg5MWI2NzlhODA1IiwiT2Zmc2V0IjowLCJTdGFydGVkQXQiOiIyMDE2LTExLTIzVDE2OjA1OjUzLjE1Njk5NzUxM1oifQ%3D%3D&digest=sha256:${DIGEST}
code: 201
body: {"Docker-Distribution-Api-Version":["registry/2.0"],"X-Content-Type-Options":["nosniff"],"Content-Length":["0"],"Date":["Wed, 23 Nov 2016 16:05:53 GMT"],"Content-Type":["text/plain; charset\u003dutf-8"],"Location":["http://<PRIVATE-REGISTRY-IP>:5000/v2/ubuntu/blobs/sha256:bf6751561805be7d07d66f6acb2a33e99cf0cc0a20f5fd5d94a3c7f8ae55c2a1"],"Docker-Content-Digest":["sha256:bf6751561805be7d07d66f6acb2a33e99cf0cc0a20f5fd5d94a3c7f8ae55c2a1"]}

curl -XPOST -H 'accept: application/json' http://<PRIVATE-REGISTRY-IP>:5000/v2/ubuntu/blobs/uploads/
response headers: {"Docker-Distribution-Api-Version":["registry/2.0"],"Docker-Upload-Uuid":["7680a9d6-7686-49a6-a6fa-44979370c2ec"],"X-Content-Type-Options":["nosniff"],"Range":["0-0"],"Content-Length":["0"],"Date":["Wed, 23 Nov 2016 16:05:53 GMT"],"Content-Type":["text/plain; charset\u003dutf-8"],"Location":["http://<PRIVATE-REGISTRY-IP>:5000/v2/ubuntu/blobs/uploads/7680a9d6-7686-49a6-a6fa-44979370c2ec?_state\u003duyI8QOIktlkc_9qynIKOXJC0FaVT6YQPlpRGfwNXHgV7Ik5hbWUiOiJ0ZXN0MDEiLCJVVUlEIjoiNzY4MGE5ZDYtNzY4Ni00OWE2LWE2ZmEtNDQ5NzkzNzBjMmVjIiwiT2Zmc2V0IjowLCJTdGFydGVkQXQiOiIyMDE2LTExLTIzVDE2OjA1OjUzLjU3NDc3ODk3OVoifQ%3D%3D"]}
code: $1
body:$2
DIGEST=$(sha256sum /home/user/container/ubuntu/6f12534822c57808e10e079842da48607c40eeb82048541320ba454af83cf021/layer.tar)
curl -XPUT -H 'accept: application/json' -d @/home/user/container/ubuntu/6f12534822c57808e10e079842da48607c40eeb82048541320ba454af83cf021/layer.tar http://<PRIVATE-REGISTRY-IP>:5000/v2/ubuntu/blobs/uploads/7680a9d6-7686-49a6-a6fa-44979370c2ec?_state=uyI8QOIktlkc_9qynIKOXJC0FaVT6YQPlpRGfwNXHgV7Ik5hbWUiOiJ0ZXN0MDEiLCJVVUlEIjoiNzY4MGE5ZDYtNzY4Ni00OWE2LWE2ZmEtNDQ5NzkzNzBjMmVjIiwiT2Zmc2V0IjowLCJTdGFydGVkQXQiOiIyMDE2LTExLTIzVDE2OjA1OjUzLjU3NDc3ODk3OVoifQ%3D%3D&digest=sha256:${DIGEST}
code: 201
body: {"Docker-Distribution-Api-Version":["registry/2.0"],"X-Content-Type-Options":["nosniff"],"Content-Length":["0"],"Date":["Wed, 23 Nov 2016 16:05:53 GMT"],"Content-Type":["text/plain; charset\u003dutf-8"],"Location":["http://<PRIVATE-REGISTRY-IP>:5000/v2/ubuntu/blobs/sha256:943edb549a8300092a714190dfe633341c0ffb483784c4fdfe884b9019f6a0b4"],"Docker-Content-Digest":["sha256:943edb549a8300092a714190dfe633341c0ffb483784c4fdfe884b9019f6a0b4"]}

curl -XPOST -H 'accept: application/json' http://<PRIVATE-REGISTRY-IP>:5000/v2/ubuntu/blobs/uploads/
response headers: {"Docker-Distribution-Api-Version":["registry/2.0"],"Docker-Upload-Uuid":["8b7245b4-9f42-42e6-8512-6b645ac233a0"],"X-Content-Type-Options":["nosniff"],"Range":["0-0"],"Content-Length":["0"],"Date":["Wed, 23 Nov 2016 16:05:54 GMT"],"Content-Type":["text/plain; charset\u003dutf-8"],"Location":["http://<PRIVATE-REGISTRY-IP>:5000/v2/ubuntu/blobs/uploads/8b7245b4-9f42-42e6-8512-6b645ac233a0?_state\u003dg5hAehwCOPnnMhfUC-Ugu_-lX9pp5NgJdTjB7cp0hO57Ik5hbWUiOiJ0ZXN0MDEiLCJVVUlEIjoiOGI3MjQ1YjQtOWY0Mi00MmU2LTg1MTItNmI2NDVhYzIzM2EwIiwiT2Zmc2V0IjowLCJTdGFydGVkQXQiOiIyMDE2LTExLTIzVDE2OjA1OjUzLjk4NDA1OTE4N1oifQ%3D%3D"]}
code: $1
body:$2
DIGEST=$(sha256sum /home/user/container/ubuntu/23a78ada034808b66348c42b9bb941901651b533b445cfb94e6b7646d2e2110d/layer.tar)
curl -XPUT -H 'accept: application/json' -d @/home/user/container/ubuntu/23a78ada034808b66348c42b9bb941901651b533b445cfb94e6b7646d2e2110d/layer.tar http://<PRIVATE-REGISTRY-IP>:5000/v2/ubuntu/blobs/uploads/8b7245b4-9f42-42e6-8512-6b645ac233a0?_state=g5hAehwCOPnnMhfUC-Ugu_-lX9pp5NgJdTjB7cp0hO57Ik5hbWUiOiJ0ZXN0MDEiLCJVVUlEIjoiOGI3MjQ1YjQtOWY0Mi00MmU2LTg1MTItNmI2NDVhYzIzM2EwIiwiT2Zmc2V0IjowLCJTdGFydGVkQXQiOiIyMDE2LTExLTIzVDE2OjA1OjUzLjk4NDA1OTE4N1oifQ%3D%3D&digest=sha256:${DIGEST}
code: 201
body: {"Docker-Distribution-Api-Version":["registry/2.0"],"X-Content-Type-Options":["nosniff"],"Content-Length":["0"],"Date":["Wed, 23 Nov 2016 16:05:54 GMT"],"Content-Type":["text/plain; charset\u003dutf-8"],"Location":["http://<PRIVATE-REGISTRY-IP>:5000/v2/ubuntu/blobs/sha256:c1bd37d01c89de343d68867518b1155cb297d8e03942066ecb44ae8f46b608a3"],"Docker-Content-Digest":["sha256:c1bd37d01c89de343d68867518b1155cb297d8e03942066ecb44ae8f46b608a3"]}

curl -XPOST -H 'accept: application/json' http://<PRIVATE-REGISTRY-IP>:5000/v2/ubuntu/blobs/uploads/
response headers: {"Docker-Distribution-Api-Version":["registry/2.0"],"Docker-Upload-Uuid":["8d97ab31-5801-4bdd-bdfd-a4878b9e7317"],"X-Content-Type-Options":["nosniff"],"Range":["0-0"],"Content-Length":["0"],"Date":["Wed, 23 Nov 2016 16:05:55 GMT"],"Content-Type":["text/plain; charset\u003dutf-8"],"Location":["http://<PRIVATE-REGISTRY-IP>:5000/v2/ubuntu/blobs/uploads/8d97ab31-5801-4bdd-bdfd-a4878b9e7317?_state\u003d0NkM--lD5vDA_wlPiPd1dEs-7WwDSmb_UfGJmMDAsIR7Ik5hbWUiOiJ0ZXN0MDEiLCJVVUlEIjoiOGQ5N2FiMzEtNTgwMS00YmRkLWJkZmQtYTQ4NzhiOWU3MzE3IiwiT2Zmc2V0IjowLCJTdGFydGVkQXQiOiIyMDE2LTExLTIzVDE2OjA1OjU1LjE5MDY1NDkzWiJ9"]}
code: $1
body:$2
DIGEST=$(sha256sum /home/user/container/ubuntu/a940c634b64a460f47e4c5d6f51e49c28280eb9e0e3da24df76b00c8c60ba756/layer.tar)
curl -XPUT -H 'accept: application/json' -d @/home/user/container/ubuntu/a940c634b64a460f47e4c5d6f51e49c28280eb9e0e3da24df76b00c8c60ba756/layer.tar http://<PRIVATE-REGISTRY-IP>:5000/v2/ubuntu/blobs/uploads/8d97ab31-5801-4bdd-bdfd-a4878b9e7317?_state=0NkM--lD5vDA_wlPiPd1dEs-7WwDSmb_UfGJmMDAsIR7Ik5hbWUiOiJ0ZXN0MDEiLCJVVUlEIjoiOGQ5N2FiMzEtNTgwMS00YmRkLWJkZmQtYTQ4NzhiOWU3MzE3IiwiT2Zmc2V0IjowLCJTdGFydGVkQXQiOiIyMDE2LTExLTIzVDE2OjA1OjU1LjE5MDY1NDkzWiJ9&digest=sha256:${DIGEST}
code: 201
body: {"Docker-Distribution-Api-Version":["registry/2.0"],"X-Content-Type-Options":["nosniff"],"Content-Length":["0"],"Date":["Wed, 23 Nov 2016 16:06:07 GMT"],"Content-Type":["text/plain; charset\u003dutf-8"],"Location":["http://<PRIVATE-REGISTRY-IP>:5000/v2/ubuntu/blobs/sha256:e7ebc6e16708285bee3917ae12bf8d172ee0d7684a7830751ab9a1c070e7a125"],"Docker-Content-Digest":["sha256:e7ebc6e16708285bee3917ae12bf8d172ee0d7684a7830751ab9a1c070e7a125"]}


curl -XPOST -H 'accept: application/json' http://<PRIVATE-REGISTRY-IP>:5000/v2/ubuntu/blobs/uploads/
response headers: {"Docker-Distribution-Api-Version":["registry/2.0"],"Docker-Upload-Uuid":["bb5ccb7c-4bf2-4a80-a78f-36cd01d139a5"],"X-Content-Type-Options":["nosniff"],"Range":["0-0"],"Content-Length":["0"],"Date":["Wed, 23 Nov 2016 16:06:08 GMT"],"Content-Type":["text/plain; charset\u003dutf-8"],"Location":["http://<PRIVATE-REGISTRY-IP>:5000/v2/ubuntu/blobs/uploads/bb5ccb7c-4bf2-4a80-a78f-36cd01d139a5?_state\u003dLyO6bZxCT0B1bfJXxnwVnsRmshIZgDvAr9VdREmmOEB7Ik5hbWUiOiJ0ZXN0MDEiLCJVVUlEIjoiYmI1Y2NiN2MtNGJmMi00YTgwLWE3OGYtMzZjZDAxZDEzOWE1IiwiT2Zmc2V0IjowLCJTdGFydGVkQXQiOiIyMDE2LTExLTIzVDE2OjA2OjA3Ljk5NDA4MjYzNFoifQ%3D%3D"]}
code: $1
body:$2
DIGEST=$(sha256sum /home/user/container/ubuntu/b7f0f1a6360ea96cc4ec0a3a28aaf8a385807ed42ceb372cd46d08d12711ad45/layer.tar)
curl -XPUT -H 'accept: application/json' -d @/home/user/container/ubuntu/b7f0f1a6360ea96cc4ec0a3a28aaf8a385807ed42ceb372cd46d08d12711ad45/layer.tar http://<PRIVATE-REGISTRY-IP>:5000/v2/ubuntu/blobs/uploads/bb5ccb7c-4bf2-4a80-a78f-36cd01d139a5?_state=LyO6bZxCT0B1bfJXxnwVnsRmshIZgDvAr9VdREmmOEB7Ik5hbWUiOiJ0ZXN0MDEiLCJVVUlEIjoiYmI1Y2NiN2MtNGJmMi00YTgwLWE3OGYtMzZjZDAxZDEzOWE1IiwiT2Zmc2V0IjowLCJTdGFydGVkQXQiOiIyMDE2LTExLTIzVDE2OjA2OjA3Ljk5NDA4MjYzNFoifQ%3D%3D&digest=sha256:${DIGEST}
code: 201
body: {"Docker-Distribution-Api-Version":["registry/2.0"],"X-Content-Type-Options":["nosniff"],"Content-Length":["0"],"Date":["Wed, 23 Nov 2016 16:06:08 GMT"],"Content-Type":["text/plain; charset\u003dutf-8"],"Location":["http://<PRIVATE-REGISTRY-IP>:5000/v2/ubuntu/blobs/sha256:f934e33a54a60630267df295a5c232ceb15b2938ebb0476364192b1537449093"],"Docker-Content-Digest":["sha256:f934e33a54a60630267df295a5c232ceb15b2938ebb0476364192b1537449093"]}


curl -XPOST -H 'accept: application/json' http://<PRIVATE-REGISTRY-IP>:5000/v2/ubuntu/blobs/uploads/
response headers: {"Docker-Distribution-Api-Version":["registry/2.0"],"Docker-Upload-Uuid":["55b5d57c-4169-4884-8068-cf3a79fc8cef"],"X-Content-Type-Options":["nosniff"],"Range":["0-0"],"Content-Length":["0"],"Date":["Wed, 23 Nov 2016 16:06:08 GMT"],"Content-Type":["text/plain; charset\u003dutf-8"],"Location":["http://<PRIVATE-REGISTRY-IP>:5000/v2/ubuntu/blobs/uploads/55b5d57c-4169-4884-8068-cf3a79fc8cef?_state\u003dy3gKd9CDD-Auw_mast0ki4dzXrO1vsnUOvv7eqZIgRl7Ik5hbWUiOiJ0ZXN0MDEiLCJVVUlEIjoiNTViNWQ1N2MtNDE2OS00ODg0LTgwNjgtY2YzYTc5ZmM4Y2VmIiwiT2Zmc2V0IjowLCJTdGFydGVkQXQiOiIyMDE2LTExLTIzVDE2OjA2OjA4LjQwNDQ5ODcwM1oifQ%3D%3D"]}
code: $1
body:$2
DIGEST=$(sha256sum /home/user/container/ubuntu/e4415b714b624040f19f45994b51daed5cbdb00e0eb9a07221ff0bd6bcf55ed7.json)
curl -XPUT -H 'accept: application/json' -d @/home/user/container/ubuntu/e4415b714b624040f19f45994b51daed5cbdb00e0eb9a07221ff0bd6bcf55ed7.json http://<PRIVATE-REGISTRY-IP>:5000/v2/ubuntu/blobs/uploads/55b5d57c-4169-4884-8068-cf3a79fc8cef?_state=y3gKd9CDD-Auw_mast0ki4dzXrO1vsnUOvv7eqZIgRl7Ik5hbWUiOiJ0ZXN0MDEiLCJVVUlEIjoiNTViNWQ1N2MtNDE2OS00ODg0LTgwNjgtY2YzYTc5ZmM4Y2VmIiwiT2Zmc2V0IjowLCJTdGFydGVkQXQiOiIyMDE2LTExLTIzVDE2OjA2OjA4LjQwNDQ5ODcwM1oifQ%3D%3D&digest=sha256:${DIGEST}
code: 201
body: {"Docker-Distribution-Api-Version":["registry/2.0"],"X-Content-Type-Options":["nosniff"],"Content-Length":["0"],"Date":["Wed, 23 Nov 2016 16:06:08 GMT"],"Content-Type":["text/plain; charset\u003dutf-8"],"Location":["http://<PRIVATE-REGISTRY-IP>:5000/v2/ubuntu/blobs/sha256:e4415b714b624040f19f45994b51daed5cbdb00e0eb9a07221ff0bd6bcf55ed7"],"Docker-Content-Digest":["sha256:e4415b714b624040f19f45994b51daed5cbdb00e0eb9a07221ff0bd6bcf55ed7"]}

curl -XPUT -H 'accept: application/json' -d @/home/user/container/ubuntu/manifest.json http://<PRIVATE-REGISTRY-IP>:5000/v2/ubuntu/manifests/16.04
code: 400
body: {"Docker-Distribution-Api-Version":["registry/2.0"],"X-Content-Type-Options":["nosniff"],"Content-Length":["118"],"Date":["Wed, 23 Nov 2016 16:06:08 GMT"],"Content-Type":["application/json; charset\u003dutf-8"]}
{"errors":[{"code":"MANIFEST_INVALID","message":"manifest invalid","detail":{"Value":"array","Type":{},"Offset":1}}]}

我还尝试使用最小内容生成手动清单,但也从清单PUT中获取错误:

{
  "schemaVersion": 2,
  "name": "ubuntu",
  "tag": "16.04",
  "fsLayers": [
    {"blobSum": "sha256:bf6751561805be7d07d66f6acb2a33e99cf0cc0a20f5fd5d94a3c7f8ae55c2a1"},
    {"blobSum": "sha256:943edb549a8300092a714190dfe633341c0ffb483784c4fdfe884b9019f6a0b4"},
    {"blobSum": "sha256:c1bd37d01c89de343d68867518b1155cb297d8e03942066ecb44ae8f46b608a3"},
    {"blobSum": "sha256:e7ebc6e16708285bee3917ae12bf8d172ee0d7684a7830751ab9a1c070e7a125"},
    {"blobSum": "sha256:f934e33a54a60630267df295a5c232ceb15b2938ebb0476364192b1537449093"}
  ]
}

其他细节: docker注册表版本:

registry github.com/docker/distribution v2.5.1

docker version:

Client:
 Version:      1.12.1
 API version:  1.24
 Go version:   go1.6.2
 Git commit:   23cf638
 Built:        Tue, 27 Sep 2016 12:25:38 +1300
 OS/Arch:      linux/amd64

Server:
 Version:      1.12.1
 API version:  1.24
 Go version:   go1.6.2
 Git commit:   23cf638
 Built:        Tue, 27 Sep 2016 12:25:38 +1300
 OS/Arch:      linux/amd64

1 个答案:

答案 0 :(得分:0)

我发现只有一篇文章真正描述了这一点,这有用。

https://www.danlorenc.com/posts/containers-part-2/

文章描述了使用V1配置和Manifest创建和上传一个图层到谷歌注册表,但它是学习这个概念的良好基础。

如果网站消失,我会把这个概念放下来,所有这些都归功于该文章的作者github.com/dlorenc

基本上在创建清单之前,您需要创建一个v1 + json配置,并将其作为blob上传,其中V1 + json配置包含带有内容摘要的图层,而不是blob。

cat <<EOF > config.json
{
  "architecture": "amd64",
  "config": {
  },
  "history": [
    {
      "created_by": "Bash!"
    }
  ],
  "os": "linux",
  "rootfs": {
    "type": "layers",
    "diff_ids": [
      "sha256:$(gunzip layer.tar.gz --to-stdout | shasum -a 256 | cut -d' ' -f1)"
    ]
  }
}
EOF

使用配置和图层,您可以定义清单:

# We need to know the size and digest of our layer and config:
size=$(wc -c layer.tar.gz | awk '{print $1}')
digest="sha256:$(shasum -a 256 layer.tar.gz | cut -d' ' -f1)"
config_size=$(wc -c config.json | awk '{print $1}')
config_digest="sha256:$(shasum -a 256 config.json | cut -d' ' -f1)"

cat << EOF > manifest.json
{
  "schemaVersion": 2,
  "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
  "config": {
    "mediaType": "application/vnd.docker.container.image.v1+json",
    "size": $config_size,
    "digest": "$config_digest"
  },
  "layers": [
    {
      "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
      "size": $size,
      "digest": "$digest"
    }
  ]
}
EOF

现在您可以上传图层:

# Check to see if the layer exists:
returncode=$(curl -w "%{http_code}" \
            -o /dev/null \
            -I http://<PRIVATE-REGISTRY-IP>:5000/v2/ubuntu/blobs/$digest)

if [[ $returncode -ne 200  ]]; then
    # Start the upload and get the location header.
    # The HTTP response seems to include carriage returns, which we need to strip
    location=$(curl -i -X POST \
               http://<PRIVATE-REGISTRY-IP>:5000/v2/ubuntu/blobs/uploads/ \
               -d "" | grep Location | cut -d" " -f2 | tr -d '\r')

    # Do the upload
    curl -X PUT $location\?digest=$digest --data-binary @layer.tar.gz
fi

上传配置,基本上与图层相同的代码:

returncode=$(curl -w "%{http_code}" -o /dev/null \
    -I http://<PRIVATE-REGISTRY-IP>:5000/v2/ubuntu/blobs/$config_digest)

if [[ $returncode -ne 200  ]]; then
    # Start the upload and get the location header.
    # The HTTP response seems to include carriage returns, which we need to strip
    location=$(curl -i -X POST \
        http://<PRIVATE-REGISTRY-IP>:5000/v2/ubuntu/blobs/uploads/ \ 
     -d "" | grep Location | cut -d" " -f2 | tr -d '\r')

    # Do the upload
    curl -X PUT $location\?digest=$config_digest --data-binary @config.json
fi

并通过推送清单来标记您的图片:

curl -X PUT \
    http://<PRIVATE-REGISTRY-IP>:5000/v2/ubuntu/manifests/16.04 --data-binary @manifest.json

备注

  • 示例代码不执行授权。
  • 不适用于openshift online starter内部注册表(400无效清单)
  • 需要手动重定向gitlab-registry,因为它返回400,其中包含blob HEADGET的位置标题