前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >私有docker registry的使用--push,pull,search,delete

私有docker registry的使用--push,pull,search,delete

作者头像
qsjs
发布2020-06-09 09:07:40
3.1K0
发布2020-06-09 09:07:40
举报

在上一节中,我们创建了基于busybox的registry image(https://cloud.tencent.com/developer/article/1640159), 在这里我们学习如何使用registry.

要使用我们的私有registry, 首先需要把这个registry运行起来。

代码语言:javascript
复制
[root@localhost docker_study]# docker history --no-trunc my_registry
IMAGE                                                                     CREATED             CREATED BY                                                                                          SIZE                COMMENT
sha256:9ed6394b8c475ed7db9d4ac43c46c3272a0fa83ec34664005a79147dfa99e32d   20 hours ago        /bin/sh -c #(nop)  VOLUME [/var/lib/registry]                                                       0 B
sha256:344ba05e52d64172e63b0b981a2406d6f52ade67f89d8a3742c3b765c96d7d73   20 hours ago        /bin/sh -c #(nop)  EXPOSE 5000/tcp                                                                  0 B
sha256:3fa5fc341acd0dc31fd8d8db843ad34bc7f6850d03a6f958551df756745ef77e   20 hours ago        /bin/sh -c #(nop)  ENTRYPOINT ["/my_entry.sh"]                                                      0 B
sha256:46cdfc9940c7866401c848ab51cc57eae72bc0b62e1eb42ce88ed681dfa4da31   20 hours ago        /bin/sh -c #(nop)  CMD ["/etc/docker/registry/config.yml"]                                          0 B
sha256:9c2c05e9dcb0629f3093c6961cbe206274167a561df87832a6c090699c2f58ee   20 hours ago        /bin/sh -c #(nop)  ENV PATH=/bin:/sbin:/usr/bin:/usr/sbin                                           0 B
sha256:bb252bad399d1f6be6da8c306ebbdcf20129361ce101ed309aa2b0219902f8a8   20 hours ago        /bin/sh -c #(nop) ADD file:3016f327a405ee7dab3301a257e2e49f1b8ea070af3d350295f507d6c1ece4c7 in /    22.1 MB
sha256:b28c46c30840253910702ac28b91effa7a6b89a90cb79708e3b55350799d6877   2 weeks ago         /bin/sh -c #(nop)  MAINTAINER PandaEye                                                              0 B
[root@localhost docker_study]# docker run -d -v /var/my_registry:/var/lib/registry -p 5000:5000 my_registry
5c9c0df9fae9980527cc3cd86bb79f4c28378cbc67373d1a8ee0440f10d43e1b
[root@localhost docker_study]# docker ps -f id=5c9c0df9fae9
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
5c9c0df9fae9        my_registry         "/my_entry.sh /etc..."   12 minutes ago      Up 12 minutes       0.0.0.0:5000->5000/tcp   admiring_lalande
[root@localhost docker_study]#

registry是docker image的仓库,可以通过push操作把 image存储到registry 。这里首先看看如何用docker push 把image存储到私有仓库中,在docker push的时候,需要用到image的tag, 而image的tag设定是有规范要求的,在man docker tag的结果中有如下的一节:

代码语言:javascript
复制
Tagging an image for a private repository
       To push an image to a private registry and not the central Docker registry you must tag it with the  registry  hostname  and
       port (if needed).
#同时附有一个例子如下:
              docker tag 0e5574283393 myregistryhost:5000/fedora/httpd:version1.0

上面的内容大概意思是:如果是要push image到私有的仓库,那么需要给这个image的tag加上私有registry的 name以及端口;

所有,我们要push image到自己的私有仓库,需要首先更改相应image的tag,使其符合规范;

代码语言:javascript
复制
[root@localhost docker_study]# docker tag my_registry:latest localhost:5000/Panda/my_registry:v1
Error parsing reference: "localhost:5000/Panda/my_registry:v1" is not a valid repository/tag
#这里的报错是因为:repository的名称不能是大写开头;修改为小写的panda重试:
[root@localhost docker_study]# docker tag my_registry:latest localhost:5000/panda/my_registry:v1
[root@localhost docker_study]# docker push localhost:5000/panda/my_registry:v1
The push refers to a repository [localhost:5000/panda/my_registry]
6469ccb2875b: Pushed
v1: digest: sha256:0614f2636b7dc16c8f95be8fff1af4252719955440317fb170abd29863a6ad37 size: 528
[root@localhost docker_study]#
#查看私有仓库中的image, 通过 /v2/_catalog 来查看:
[root@localhost docker_study]# curl -X GET  http://localhost:5000/v2/_catalog
{"repositories":["panda/my_registry"]}
[root@localhost docker_study]#
#查看私有仓库中特定image的tag,通过/v2/<REPONAME>/<IMAGENAME>/tags/list:
[root@localhost docker_study]# curl http://localhost:5000/v2/panda/my_registry/tags/list
{"name":"panda/my_registry","tags":["v1"]}
[root@localhost docker_study]#
#再push一个image到私有仓库;
[root@localhost docker_study]# docker push localhost:5000/panda/my_baseimage:v1
The push refers to a repository [localhost:5000/panda/my_baseimage]
3a3144cdb2db: Pushed
4acd2d6fd644: Pushed
e6c6f0833491: Pushed
8d5d5c2c3059: Pushed
v1: digest: sha256:39ad17c3e10f902d8b098ee5128a87d4293b6d07cbc2d1e52ed9ddf0076e3cf9 size: 1156
#查看私有仓库中有两个image. 都位于同一个repository: panda
[root@localhost docker_study]# curl -X GET  http://localhost:5000/v2/_catalog
{"repositories":["panda/my_baseimage","panda/my_registry"]}
[root@localhost docker_study]#

上面我们已经成功把image push到了私有仓库中,那么我们接着看看如何从私有registry中把image pull 到本地, 首先查看docker pull 的帮助文档, 发现有如下一节:

代码语言:javascript
复制
Pull a repository with multiple images
       By default, docker pull pulls a single image from the registry. A repository can contain multiple images. To pull all images
       from a repository, provide the -a (or --all-tags) option when using docker pull.

也就是说,docker pull的时候,默认是只pull一个image, 但是也可以把所有版本的image都pull下来,如果需要这样做,那么需要加上 -a 参数就可以了. 看下面的例子:

代码语言:javascript
复制
[root@localhost docker_study]# docker pull  192.168.0.110:5000/panda/my_baseimage
Using default tag: latest
Trying to pull repository 192.168.0.110:5000/panda/my_baseimage ...
Pulling repository 192.168.0.110:5000/panda/my_baseimage
Error: image panda/my_baseimage:latest not found
#没有加 -a 参数的时候,总是试图pull最新version的image, 而version 为latest的image并不存在,所以报错;
#下面加上-a参数,会获取所有version的 my_baseimage, 所以就没有报错;
[root@localhost docker_study]# docker pull -a 192.168.0.110:5000/panda/my_baseimage
Trying to pull repository 192.168.0.110:5000/panda/my_baseimage ...
v1: Pulling from 192.168.0.110:5000/panda/my_baseimage
Digest: sha256:39ad17c3e10f902d8b098ee5128a87d4293b6d07cbc2d1e52ed9ddf0076e3cf9
Status: Image is up to date for 192.168.0.110:5000/panda/my_baseimage
[root@localhost docker_study]#

你可能还记得docker push的时候,需要通过image的tag来标志registry的地址,那么docker pull的时候,是否也需要如此呢?

因为一个registry可能通过ip, url 访问到,所以在docker pull的时候,只需要指定其中一个可以访问到的方式就行,没有像docker push时候那样严格的要求,在上面的例子中,192.168.0.110就是本机的IP地址,所以可以通过192.168.0.110来pull, 当然也可以用127.0.0.1或者localhost.

除了docker push, docker pull, 我们用的最多可能是docker search , 那么怎么search 私有registry呢? man docker search的结果告诉我们:

代码语言:javascript
复制
DESCRIPTION
       Search  Docker  Hub  for  images  that match the specified TERM. The table of images returned displays the name, description
       (truncated by default), number of stars awarded, whether the image is official, and whether it is automated.
       Note - Search queries will only return up to 25 results

以上是说,docker search 是search docker hub, 并且返回最多25个results. 关键是没有说如何才能search 私有的registry. 也就是说,docker search 在registry v2版本中是不支持docker search 私有镜像的;这时候,我们需要通过V2版本中提供的REST API 配合shell命令来完成查找请求(REST API的简介,请参照章节:registry(v2)的REST API 简要学习)。下面的例子展示了如何进行查找:

代码语言:javascript
复制
#在这里我们查找名字包含base的image
#利用GET方法获得的结果是json格式,然后用python的json.tool进行处理,接着用sed 进行关键字匹配,最后输出匹配结果;
[root@localhost sysconfig]# curl -X GET http://localhost:5000/v2/_catalog 2>/dev/null | python -m json.tool | sed -n '/base/p'
        "panda/my_baseimage",
[root@localhost sysconfig]#
#输出所有匹配my关键字的image:
[root@localhost sysconfig]# curl -X GET http://localhost:5000/v2/_catalog 2>/dev/null | python -m json.tool | sed -n '/my/p'
        "panda/my_baseimage",
        "panda/my_registry"
[root@localhost sysconfig]#

以上分别介绍了如何使用私有仓库进行基本的push, pull, search ,还有一个常用的需求就是从私有仓库删除不需要的image. 这个在docker 的命令中也没有直接的提供;这时候依然需要用REST API的方式来实现删除操作,实际上,用下面的方法删除的仅仅是manifests文件,而并不会删除相应的image layer. 看下面的例子:

代码语言:javascript
复制
#尝试删除my_baseimage的manifests文件, 但是发现报错了;
[root@localhost sysconfig]# curl -X DELETE http://localhost:5000/v2/panda/my_baseimage/manifests/v1 2>/dev/null | python -m json.tool
{
    "errors": [
        {
            "code": "UNSUPPORTED",
            "message": "The operation is unsupported."
        }
    ]
}
[root@localhost sysconfig]#
#经网上搜索,是因为环境变量的原因,需要添加以下的启动参数REGISTRY_STORAGE_DELETE_ENABLED=true
#那么让我们停止之前的容器,重新run registry容器,如下:
[root@localhost sysconfig]# docker run -d -v /var/my_registry:/var/lib/registry -e REGISTRY_STORAGE_DELETE_ENABLED=true  -p 5000:5000 my_registry
658ce36ca5f98a718c951ce30d5acc54de5c08e49a6daf2ffc19d97c0c88923b
#执行删除manifests文件的操作;
[root@localhost sysconfig]# curl -X DELETE http://localhost:5000/v2/panda/my_baseimage/manifests/v1 2>/dev/null | python -m json.tool
{
    "errors": [
        {
            "code": "DIGEST_INVALID",
            "message": "provided digest did not match uploaded content"
        }
    ]
}
[root@localhost sysconfig]#
#这里又发现了新的报错:digest不对,看来这个reference并不能使用tag, 只能用digest, 那么如何获取digest呢?继续尝试
[root@localhost sysconfig]# curl -X GET  --head http://localhost:5000/v2/panda/my_baseimage/manifests/v1
HTTP/1.1 200 OK
Content-Length: 8841
Content-Type: application/vnd.docker.distribution.manifest.v1+prettyjws
Docker-Content-Digest: sha256:87df0cb822cd407bf78104d9c5449bea0b1dfa4bae413a32efe91ebb78ee9da0
Docker-Distribution-Api-Version: registry/2.0
Etag: "sha256:87df0cb822cd407bf78104d9c5449bea0b1dfa4bae413a32efe91ebb78ee9da0"
X-Content-Type-Options: nosniff
Date: Sun, 29 Sep 2019 14:13:42 GMT
#用获取到的sha256值作为reference, 再次进行删除操作;
[root@localhost sysconfig]# curl -X DELETE http://localhost:5000/v2/panda/my_baseimage/manifests/87df0cb822cd407bf78104d9c5449bea0b1dfa4bae413a32efe91ebb78ee9da0
{"errors":[{"code":"DIGEST_INVALID","message":"provided digest did not match uploaded content"}]}
[root@localhost sysconfig]#
#很遗憾,又一次失败了,还是因为digests不对,怎么办呢?查找万能的互联网,终于找到原因: 
#需要添加 --header "Accept: application/vnd.docker.distribution.manifest.v2+json" 参数才可以获取到正确的digests值。
[root@localhost sysconfig]# curl --header "Accept: application/vnd.docker.distribution.manifest.v2+json" -I  http://localhost:5000/v2/panda/my_baseimage/manifests/v1
HTTP/1.1 200 OK
Content-Length: 1156
Content-Type: application/vnd.docker.distribution.manifest.v2+json
Docker-Content-Digest: sha256:39ad17c3e10f902d8b098ee5128a87d4293b6d07cbc2d1e52ed9ddf0076e3cf9
Docker-Distribution-Api-Version: registry/2.0
Etag: "sha256:39ad17c3e10f902d8b098ee5128a87d4293b6d07cbc2d1e52ed9ddf0076e3cf9"
X-Content-Type-Options: nosniff
Date: Sun, 29 Sep 2019 14:26:20 GMT
[root@localhost sysconfig]# curl -X DELETE http://localhost:5000/v2/panda/my_baseimage/manifests/39ad17c3e10f902d8b098ee5128a87d4293b6d07cbc2d1e52ed9ddf0076e3cf9
{"errors":[{"code":"DIGEST_INVALID","message":"provided digest did not match uploaded content"}]}
#再次失败,我是按照官方说法获取到了正确的digests之啊,但是还是失败,为什么???
#再次检查,发现在reference中少写了关键字“sha256:”, 最后再次尝试:
[root@localhost sysconfig]# curl -X DELETE http://localhost:5000/v2/panda/my_baseimage/manifests/sha256:39ad17c3e10f902d8b098ee5128a87d4293b6d07cbc2d1e52ed9ddf0076e3cf9
#上面的删除没有报错,终于成功了,然后重新尝试获取manifests中的digests,结果为空,如下:
[root@localhost sysconfig]# curl --header "Accept: application/vnd.docker.distribution.manifest.v2+json"   -I   -X HEAD http://127.0.0.1:5000/v2/panda/my_baseimage/manifests/v1
HTTP/1.1 404 Not Found
Content-Type: application/json; charset=utf-8
Docker-Distribution-Api-Version: registry/2.0
X-Content-Type-Options: nosniff
Date: Sun, 29 Sep 2019 14:42:22 GMT
Content-Length: 92
[root@localhost sysconfig]#
#我们看看image是否发生了变化:
[root@localhost sysconfig]# curl -X GET http://localhost:5000/v2/_catalog
{"repositories":["panda/my_baseimage","panda/my_registry"]}
#这里说明虽然删除了manifests,但是image依然可以看到;并没有被删除;
#尝试拉取这个image,看是否可以成功:
[root@localhost sysconfig]# docker pull -a 192.168.0.110:5000/panda/my_baseimage
Trying to pull repository 192.168.0.110:5000/panda/my_baseimage ...
Status: Image is up to date for 192.168.0.110:5000/panda/my_baseimage
[root@localhost sysconfig]# docker images | grep my_baseimage
[root@localhost sysconfig]#
#从上面的结果可以看到,虽然提示up to date, 但是本地并没有成功pull到这个image

从这个过程中,可以知道:

A. 删除manifests文件并不会删除image 的各个layer层;所以不会释放layer占用的空间

B. 删除manifests会导致pull操作失效,因为pull操作需要manifests这个文件;

C. 通过REST API的方式依然可以看到丢失了manifests文件的image。

到这里为止,我们知道了如何从registry获取image的digests ID, 并利用digests ID删除对应的manifests文件, 可以认为manifests文件就是image的元数据文件;但是,如果我们需要删除对应的layer来释放空间,那应该怎么做呢?

代码语言:javascript
复制
#查看删除了manifests之后的磁盘使用状态:
[root@localhost v2]# du -hsx * 
80M blobs  #blobs 占用了80M
28K repositories
[root@localhost v2]# pwd 
/var/my_registry/docker/registry/v2
[root@localhost v2]# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
8ed26727c8bb        my_registry         "/my_entry.sh /etc..."   18 minutes ago      Up 18 minutes       0.0.0.0:5000->5000/tcp   goofy_austin
#进入运行中的registry容器;
[root@localhost v2]# docker exec -it 8ed26727c8bb /bin/sh
#运行registry garbage-collect命令;其输出的结果提示有三个blobs 可以被删除;并给出了相应的路径,以及digests值;同时自动帮我们删除了这些blobs;
/ # registry garbage-collect /etc/docker/registry/config.yml 
panda/my_baseimage
panda/my_registry
panda/my_registry: marking manifest sha256:7022fc0185a773a8b7a75f624ef91b8b6fb03fafd9bf667cb90af95691129d00 
panda/my_registry: marking blob sha256:48d8ea6b3745a4782ee98ae132a37bd054d6589c170f3e3db133b693e092dfaa
panda/my_registry: marking blob sha256:fc321dfdd8e9649a4db2ce20c2ef1f523ed20b38aa5fb2328feebb41f1936497

3 blobs marked, 3 blobs and 0 manifests eligible for deletion
blob eligible for deletion: sha256:67fa590cfc1c207c30b837528373f819f6262c884b7e69118d060a0c04d70ab8
INFO[0000] Deleting blob: /docker/registry/v2/blobs/sha256/67/67fa590cfc1c207c30b837528373f819f6262c884b7e69118d060a0c04d70ab8  go.version=go1.11.2 instance.id=b49fe9db-3eb1-46d6-b918-44935820a9bb service=registry
blob eligible for deletion: sha256:a36b9e68613d07eec4ef553da84d0012a5ca5ae4a830cf825bb68b929475c869
INFO[0000] Deleting blob: /docker/registry/v2/blobs/sha256/a3/a36b9e68613d07eec4ef553da84d0012a5ca5ae4a830cf825bb68b929475c869  go.version=go1.11.2 instance.id=b49fe9db-3eb1-46d6-b918-44935820a9bb service=registry
blob eligible for deletion: sha256:d8d02d45731499028db01b6fa35475f91d230628b4e25fab8e3c015594dc3261
INFO[0000] Deleting blob: /docker/registry/v2/blobs/sha256/d8/d8d02d45731499028db01b6fa35475f91d230628b4e25fab8e3c015594dc3261  go.version=go1.11.2 instance.id=b49fe9db-3eb1-46d6-b918-44935820a9bb service=registry
/ # exit
#删除完成,退出容器,查看占用的空间,blobs 占用空间从之前的80M减小到当前的7.8M;
[root@localhost v2]# du -hsx *
7.8M    blobs
28K repositories
[root@localhost v2]# 
#重启对应的容器,并进行如下的验证:
[root@localhost v2]# docker stop 8ed26727c8bb
8ed26727c8bb
[root@localhost v2]# docker start 8ed26727c8bb
8ed26727c8bb
[root@localhost v2]# docker ps -a 
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
8ed26727c8bb        my_registry         "/my_entry.sh /etc..."   33 minutes ago      Up 7 seconds        0.0.0.0:5000->5000/tcp   goofy_austin
[root@localhost v2]# curl -XGET localhost:5000/v2/_catalog
{"repositories":["panda/my_baseimage","panda/my_registry"]}
#这里发现my_baseimage依然存在,回看前面的步骤,registry命令只是帮忙清除了无用的blobs,并没有清除my_baseimage. 我们无需进入容器,直接在挂载点删除对应的my_baseimage. 
[root@localhost panda]# pwd
/var/my_registry/docker/registry/v2/repositories/panda
[root@localhost panda]# rm -rf my_baseimage/
#重新查看,我们发现终于没有my_baseimage这个image了
[root@localhost panda]# curl -XGET localhost:5000/v2/_catalog
{"repositories":["panda/my_registry"]}
[root@localhost panda]# 

至此,完成了image的彻底删除操作;总结一下,要完成删除一个image需要以下的步骤:

1.首先删除image的manifests文件,这个过程需要获得image的digests ID, 而要正确获得该ID, 需要添加特殊的请求头: --header "Accept: application/vnd.docker.distribution.manifest.v2+json" , 该步骤可以导致pull 操作失效;

2.需要删除对应的blobs, 这个可以通过: registry garbage-collect CONFIG-FILE 来完成;可以清理掉layer占用的空间问题;

3.需要删除对应的repository, 这个必须手动删除才可以;

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 至此,完成了image的彻底删除操作;总结一下,要完成删除一个image需要以下的步骤:
相关产品与服务
容器镜像服务
容器镜像服务(Tencent Container Registry,TCR)为您提供安全独享、高性能的容器镜像托管分发服务。您可同时在全球多个地域创建独享实例,以实现容器镜像的就近拉取,降低拉取时间,节约带宽成本。TCR 提供细颗粒度的权限管理及访问控制,保障您的数据安全。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档