docker registry的使用--push,pull,se
在上一节中,我们创建了基于busybox的registry image(https://www.jianshu.com/p/07a1d118ba17), 在这里我们学习如何使用registry.
要使用我们的私有registry, 首先需要把这个registry运行起来。
[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的结果中有如下的一节:
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,使其符合规范;
[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 的帮助文档, 发现有如下一节:
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 参数就可以了. 看下面的例子:
[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的结果告诉我们:
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 简要学习)。下面的例子展示了如何进行查找:
#在这里我们查找名字包含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. 看下面的例子:
#尝试删除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。
本文原创,转载请注明出处