私有仓库的搭建与管理
Docker Registry 简介
怎样在几个机器之间使用同一个镜像?难道要先上传到官方的仓库,另几个机器去下载吗?当然不是了,最好的方法就是搭建一个本地的仓库。 Docker Registry 就是官方提供的搭建本地仓库的方案,它有两种搭建方式, http 与 https ,如果你只简单的在本地使用,第一种就足够了,如果考虑到安全方面,就用 https ,这种方式当然就需要为你的仓库服务器申请证书了,或者自建一个证书机构,自已为自已颁发证书。本文只介绍 http 方式,并介绍仓库的上传、下载、查询、删除等常用操作。
环境描述
假设我有三台机器,他它们的/etc/hosts文件包含如下内容:
[user@ser1 ~]$ cat /etc/hosts
10.100.100.101 ser1.node.com registry.io
10.100.100.102 ser2.node.com
10.100.100.103 ser3.node.com
很显然,我要在第一台机器上部署 Docker Registry ,并且这三台机器都已安装好了Docker服务
Docker Registry 搭建
官方提供的私有仓库是以镜像像方式提供的,也就是说你只要把这个镜像下载下来启动就可以了,当然还要自已定制一些运行参数。 关于所有可配置项,可以去官网查看,具体地址在本文尾部。
在第一台机器上运行官方提供的 Registry 容器
sudo mkdir -p /data/docker-registry
docker run -dt \
--name registry \
-p 10.100.100.101:5000:5000 \
--restart=always \
-v /data/docker-registry:/var/lib/registry \
-e REGISTRY_STORAGE_DELETE_ENABLED=true \
-e REGISTRY_STORAGE_DELETE_REDIRECT=true \
registry:2
参数说明:
-p 10.100.100.101:5000:5000
这是把容器的端口映射到物理机,这样在其它机器直接访问物理机就相当于访问仓库了
--restart=always
这个参数可以让容器在发生意外的时候还可以自已启动,比如当我重启 Docker 服务的时候
-v /data/docker-registry:/var/lib/registry
找一个容量大的挂载点映射给容器,用来存放上传的镜像
-e
最后这两个是让我们可以远程删除已经上传的镜像
看下启动了没有
[user@ser1 ~]$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
867106b006da registry:2 "/entrypoint.sh /etc/" 10 seconds ago Up 10 seconds 10.100.100.101:5000->5000/tcp registry
候改其它每台机器上的 Docker 配置文件,使得其它机器信任此仓库,在其配置文件中找到ExecStart一行,在后面追加内容 –insecure-registry registry.io:5000 这里以 CentOS7 为例,如下:
[user@ser1 ~]$ sudo vi /usr/lib/systemd/system/docker.service
...
[Service]
ExecStart=/usr/bin/dockerd --insecure-registry registry.io:5000
ExecReload=/bin/kill -s HUP $MAINPID
...
重新启动 Docker 服务,使配置生效
sudo systemctl daemon-reload ; sudo systemctl restart docker
我们在第二台机器上,上传一个镜像试一下
[user@ser2 ~]$ docker images # 看一下本地有哪些镜像
paulczar/glusterfs latest dc2e1257bba4 2 years ago 277 MB
[user@ser2 ~]$ docker tag paulczar/glusterfs:latest registry.io:5000/glusterfs # 修改镜像名
[user@ser2 ~]$ docker push registry.io:5000/glusterfs # 上传到自已的仓库
2e92feb4cbe1: Pushing [==============================> ] 189.1 MB/277 MB
OK!!,顺利上传至我们的私有仓库,而且速度很快
Docker Registry REST API 简介
有了自已的仓库,那我们想看一下仓库中已经上传了哪些镜像,或者想删除自已上传的镜像,怎么办?难道我要去看 /data/docker-registry 目录下的内容??不用担心,官方已经提供了方法, Registry 本身对外提供了 HTTP 操作接口,很方便。 先看一个例子,下面这条命令是测试 registry 版本是不是2.x版本的,这里我们在ser2这台机器上执行
[user@ser2 ~]$ curl -i -X GET registry.io:5000/v2/
HTTP/1.1 200 OK
Content-Length: 2
Content-Type: application/json; charset=utf-8
Docker-Distribution-Api-Version: registry/2.0
X-Content-Type-Options: nosniff
Date: Sat, 21 Jan 2017 14:13:25 GMT
注意看输出信息的第一行,响应码200表示请求成功,也就是说我们的 registry 版本确实是2.x版本
查看仓库中的镜像
那我们再来一条命令,看一下我们已经上传的的有镜像
[user@ser2 ~]$ curl -H "Docker-Distribution-API-Version: registry/2.0" -X GET registry.io:5000/v2/_catalog {"repositories":["glusterfs"]}
它返回了一个Json串,里面包含了我们刚刚上传的镜像,是不是很棒??但聪明的你也许已经发现,这个返回的信息里应该包含镜像标签的啊,后面不是应该有个:latest吗? 不着急,再来一条命令,用来查询某一镜像的所有标签(或者说版本)
[user@ser2 ~]$ curl -H "Docker-Distribution-API-Version: registry/2.0" -X GET registry.io:5000/v2/glusterfs/tags/list {"name":"glusterfs","tags":["latest"]}
看到了吧,如果有多个tag的话,这里会全部列出来
删除仓库中的镜像
删除要稍麻烦一点,分两步
先获取某镜像的 digest (返回的消息头中的 Docker-Content-Digest 后面部分)
[user@ser2 ~]$ curl -H "Authorization: Basic <hash_here>" -i -X GET \
-H "Accept: application/vnd.docker.distribution.manifest.v2+json" \
http://registry.io:5000/v2/glusterfs/manifests/v1
HTTP/1.1 200 OK
Content-Length: 745
Content-Type: application/vnd.docker.distribution.manifest.v2+json
Docker-Content-Digest: sha256:97de138832d894bf87af449c012538fe1c94dd078a2dc8941f0790f498738c4a
Docker-Distribution-Api-Version: registry/2.0
Etag: "sha256:97de138832d894bf87af449c012538f31c94dd078a2dc8941f0790f498738c4a"
X-Content-Type-Options: nosniff
Date: Sat, 21 Jan 2017 14:41:32 GMT
{
"schemaVersion": 2,
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"config": {
"mediaType": "application/vnd.docker.container.image.v1+json",
"size": 1232,
"digest": "sha256:78f3c04c6b8654dd86d0e09148dac08f34eaddd008aeb2926cd6a3a74j84f3d5"
},
"layers": [
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 1300037181,
"digest": "sha256:065b2f8d16ae85886f19afb12a9ed3eaad2k04484a6143f218ebb39eac43a61d"
},
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 5600560669,
"digest": "sha256:f074337a2c9c17aaf3ce1ed9edcb8b08cbc5e3f730032b721917f24a8920a653"
}
]
}
然后用上面返回的消息头中的 Docker-Content-Digest 后面的值,带入下一条命令
[user@ser2 ~]$ curl -H "Accept: application/vnd.docker.distribution.manifest.v2+json" -i -X DELETE \
http://registry.io:5000/v2/glusterfs/manifests/sha256:97de138832d894bf87af449c012538fe1c94dd078a2dc8941f0790f498738c4a
HTTP/1.1 200 OK
...
返回码200表示删除成功了,但是!!这里注意一下,此时镜像并不一定是真的被从仓库中的物理机上删除了,大部分情况下只是让我们看不到了而已,为什么说不一定呢?这要从镜像的组成原理说起,一个镜像通常是由多个层组成的,理论上,只有我们删除的这个镜像的所有依赖的层都被删了,它才可能被真正删除,而在我多次实验中,即使把所有的层都删除了,镜像也没有从物理机上消失,不知为何,感兴趣的朋友可以试下。