1. 关于Registry
官方的Docker hub是一个用于管理公共镜像的好地方,我们可以在上面找到我们想要的镜像,也可以把我们自己的镜像推送上去。但是,有时候,我们的使用场景需要我们拥有一个私有的镜像仓库用于管理我们自己的镜像。这个可以通过开源软件Registry来达成目的。
Registry在github上有两份代码:老代码库和新代码库。老代码是采用python编写的,存在pull和push的性能问题,出到0.9.1版本之后就标志为deprecated,不再继续开发。从2.0版本开始就到在新代码库进行开发,新代码库是采用go语言编写,修改了镜像id的生成算法、registry上镜像的保存结构,大大优化了pull和push镜像的效率。
官方在Docker hub上提供了registry的镜像(详情),我们可以直接使用该registry镜像来构建一个容器,搭建我们自己的私有仓库服务。Tag为latest的registry镜像是0.9.1版本的,我们直接采用2.1.1版本。
2. Registry的部署
运行下面命令获取registry镜像,
$ sudo docker pull registry
然后启动一个容器,
$ sudo docker run -d -v /data/registry:/var/lib/registry -p 5000:5000 --restart=always --name docker-registry registry
Registry服务默认会将上传的镜像保存在容器的/var/lib/registry,我们将主机的/data/registry目录挂载到该目录,即可实现将镜像保存到主机的/data/registry目录了。
运行docker ps看一下容器情况,
$ sudo docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES bdb470c86d4f registry "/entrypoint.sh /e..." 2 days ago Up 2 days 0.0.0.0:5000->5000/tcp docker-registry
说明我们已经启动了registry服务,打开浏览器输入http://10.1.12.114:5000/v2/_catalog,出现下面情况说明registry运行正常,
3. 验证
现在我们通过将镜像push到registry来验证一下。
我的机器上有个hello-world的镜像,我们要通过docker tag将该镜像标志为要推送到私有仓库,
$ sudo docker tag hello-world 10.1.12.114:5000/hello-world
然后查看以下本地的镜像,
sudo docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE registry 2.1.1 b91f745cd233 5 days ago 220.1 MB ubuntu 14.04 a5a467fddcb8 6 days ago 187.9 MB hello-world latest 975b84d108f1 2 weeks ago 960 B 127.0.0.1:5000/hello-world latest 975b84d108f1 2 weeks ago 960 B
接下来,我们运行docker push将hello-world镜像push到我们的私有仓库中,
sudo docker push 10.1.12.114/hello-world The push refers to a repository [127.0.0.1:5000/hello-world] (len: 1) 975b84d108f1: Image successfully pushed 3f12c794407e: Image successfully pushed latest: digest: sha256:1c7adb1ac65df0bebb40cd4a84533f787148b102684b74cb27a1982967008e4b size: 2744
现在我们可以查看我们本地/data/registry目录下已经有了刚推送上来的hello-world。我们也在浏览器中输入http://10.1.12.114:5000/v2/_catalog,如下图所示,
现在我们可以先将我们本地的127.0.0.1:5000/hello-world和hello-world先删除掉,
$ sudo docker rmi hello-world $ sudo docker rmi 127.0.0.1:5000/hello-world
然后使用docker pull从我们的私有仓库中获取hello-world镜像,
[root@devopsdb1 data]# docker pull 10.1.12.114:5000/eiki/hello-world
Using default tag: latest
latest: Pulling from eiki/hello-world
Digest: sha256:aea2c7bc314d5015556c3725dbcb66c739d9d7acc6df0681368d1b9aae3c9cd9
Status: Downloaded newer image for 10.1.12.114:5000/eiki/hello-world:latest
[root@devopsdb1 data]#
[root@devopsdb1 data]#
[root@devopsdb1 data]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
eiki/archer v5.0 6ab11c7834d6 2 days ago 1.24GB
registry latest d0eed8dad114 3 weeks ago 25.8MB
alpine latest caf27325b298 3 weeks ago 5.52MB
10.1.12.114:5000/eiki/hello-world latest fce289e99eb9 7 weeks ago 1.84kB
hello-world latest fce289e99eb9 7 weeks ago 1.84kB
percona/pmm-server latest 2ff436aaddc9 3 months ago 1.01GB
eiki/centos v7.5 77b035dbe273 5 months ago 343MB
swarm latest ff454b4a0e84 8 months ago 12.7MB
shipyard/docker-proxy latest cfee14e5d6f2 3 years ago 9.46MB
4. 可能问题
可能会出现无法push镜像到私有仓库的问题。这是因为我们启动的registry服务不是安全可信赖的。这是我们需要修改docker的配置文件/etc/docker/daemon.json,添加下面的内容,
{
"registry-mirrors": [
"https://2lqq34jg.mirror.aliyuncs.com",
"https://pee6w651.mirror.aliyuncs.com",
"https://registry.docker-cn.com",
"http://hub-mirror.c.163.com"
],
"dns": ["8.8.8.8","8.8.4.4"],
"insecure-registries":["10.1.12.114:5000"]
}
然后重启docker后台进程,
$ systemctl restart docker
这是再push即可。
5.Registry删除镜像、垃圾回收
Docker仓库在2.1版本中支持了删除镜像的API,但这个删除操作只会删除镜像元数据,不会删除层数据。在2.4版本中对这一问题进行了解决,增加了一个垃圾回收命令,删除未被引用的层数据
查看仓库镜像 (查看仓库镜像脚本 get.py)
首先安装epel扩展源:
yum -y install epel-release 更新完成之后,就可安装pip: yum -y install python-pip 安装完成之后清除cache: yum clean all
request模块安装:
pip install request
创建python脚本:
#!/usr/bin/env python #-*- coding:utf-8 -*- import requests import json import traceback repo_ip = '10.1.12.114' repo_port = 5000 def getImagesNames(repo_ip,repo_port): docker_images = [] try: url = "http://" + repo_ip + ":" +str(repo_port) + "/v2/_catalog" res =requests.get(url).content.strip() res_dic = json.loads(res) images_type = res_dic['repositories'] for i in images_type: url2 = "http://" + repo_ip + ":" +str(repo_port) +"/v2/" + str(i) + "/tags/list" res2 =requests.get(url2).content.strip() res_dic2 = json.loads(res2) name = res_dic2['name'] tags = res_dic2['tags'] for tag in tags: docker_name = str(repo_ip) + ":" + str(repo_port) + "/" + name + ":" + tag docker_images.append(docker_name) print docker_name except: traceback.print_exc() return docker_images a=getImagesNames(repo_ip, repo_port) #print a
[root@devopsdb1 script]# python get.py
10.1.12.114:5000/eiki/archer:latest
10.1.12.114:5000/eiki/archer:v2.0
10.1.12.114:5000/eiki/hello-world:latest
查看数据进行仓库容器中,通过du命令查看大小
[root@devopsdb1 script]# docker exec -it docker-registry sh
/ # du -chs /var/lib/registry/
681.9M /var/lib/registry/
681.9M total
删除镜像
删除镜像对应的API如下:
DELETE /v2/<name>/manifests/<reference>
name:镜像名称
reference: 镜像对应sha256值
垃圾回收
进行容器执行垃圾回收命令
registry garbage-collect /etc/docker/registry/config.yml