如何搭建及使用docker registry

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何搭建及使用docker registry相关的知识,希望对你有一定的参考价值。

参考技术A registry是什么?
registry是Docker的镜像存储服务,docker hub上的registry镜像见Registry官方镜像,更多详细信息请参见源码。
搭建registry
在服务器上执行如下命令安装docker,这里选择腾讯云(Ubuntu Server 14.04.1 LTS 64位)镜像来创建服务器
curl -fsSL https://get.docker.com/ | sh

安装docker-compose Docker Compose是一个定义及运行多个Docker容器的工具。使用Docker Compose只需要在一个配置文件中定义多个Docker容器,然后使用一条命令将多个容器启动,Docker Compose会通过解析容器间的依赖关系,按先后顺序启动所定义的容器。详见Docker Compose
curl -L https://github.com/docker/compose/releases/download/1.8.0/docker-compose-$(uname -s)-$(uname -m) > /usr/local/bin/docker-compose
chmod a+x /usr/local/bin/docker-compose

启动registry服务,此例中包含nginx和registry两个容器,涉及的包及配置文件请参见附件,解压后,直接执行如下命令即可创建服务。
docker-compose up -d

停止服务
docker-compose stop

重启服务
docker-compose restart

下线服务
docker-compose down

上传镜像
因为上面搭建的registry服务是http的,所以docker启动参数需要配置--insecure-registry localhost选项,修改/etc/default/docker文件
DOCKER_OPTS="--insecure-registry localhost"

重启docker
service docker restart

拉取上传镜像 docker pull;docker tag;docker push(tag默认为latest)
docker pull hello-world
docker tag hello-world localhost/library/hello-world
docker push localhost/library/hello-world

下载镜像
docker pull localhost/library/hello-world

删除镜像
docker rmi localhost/library/hello-world

获取镜像仓库列表
# curl http://localhost/v2/_catalog
"repositories":["library/hello-world"]

未上传镜像前的输出如下:
# curl http://localhost/v2/_catalog
"repositories":[]

获取镜像tag列表
# curl -X GET http://localhost/v2/library/hello-world/tags/list
"name":"library/hello-world","tags":["latest"]

获取镜像manifests信息
# curl -H "Accept: application/vnd.docker.distribution.manifest.v2+json" -X GET http://localhost/v2/library/hello-world/manifests/latest

"schemaVersion": 2,
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"config":
"mediaType": "application/vnd.docker.container.image.v1+json",
"size": 1473,
"digest": "sha256:c54a2cc56cbb2f04003c1cd4507e118af7c0d340fe7e2720f70976c4b75237dc"
,
"layers": [

"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 974,
"digest": "sha256:c04b14da8d1441880ed3fe6106fb2cc6fa1c9661846ac0266b8a5ec8edf37b7c"

]


其中c54a2cc56cbb2f04003c1cd4507e118af7c0d340fe7e2720f70976c4b75237dc即为执行docker images时看到的IMAGE ID。 layers表示了镜像的层次关系,可以通过layers中的digest来拉取blob,见下面获取镜像blob
获取镜像blob
在上面获取hello-world:latest镜像的manifests信息中可以看到其只有一个layer,以此为例来看如何获取镜像blob。从拉取的结果可以看到获取的blob与文件sha256是一致的。执行docker pull实际上就是首先获取到镜像的manifests信息后,再拉取blob的。
# curl -s -X GET http://localhost/v2/library/hello-world/blobs/sha256:c04b14da8d1441880ed3fe6106fb2cc6fa1c9661846ac0266b8a5ec8edf37b7c -o hello-world.blob
# ls -l hello-world.blob
-rw-r--r-- 1 root root 974 Nov 23 09:56 hello-world.blob
# sha256sum hello-world.blob
c04b14da8d1441880ed3fe6106fb2cc6fa1c9661846ac0266b8a5ec8edf37b7c hello-world.blob

##删除镜像(soft delete)
首先通过curl -i 参数获取到镜像的Docker-Content-Digest,registry 2.3及以后的版本必须在header中指定Accept: application/vnd.docker.distribution.manifest.v2+json,否则默认返回的是schema1的digest,其与schema2的digest不同,使用不指定上述头信息返回的digest删除时会返回404。
# curl -i -H "Accept: application/vnd.docker.distribution.manifest.v2+json" -X GET http://localhost/v2/library/hello-world/manifests/latest

HTTP/1.1 200 OK
Server: nginx/1.11.5
Date: Wed, 23 Nov 2016 02:17:51 GMT
Content-Type: application/vnd.docker.distribution.manifest.v2+json
Content-Length: 524
Connection: keep-alive
Docker-Content-Digest: sha256:a18ed77532f6d6781500db650194e0f9396ba5f05f8b50d4046b294ae5f83aa4
Docker-Distribution-Api-Version: registry/2.0
Etag: "sha256:a18ed77532f6d6781500db650194e0f9396ba5f05f8b50d4046b294ae5f83aa4"


"schemaVersion": 2,
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"config":
"mediaType": "application/vnd.docker.container.image.v1+json",
"size": 1473,
"digest": "sha256:c54a2cc56cbb2f04003c1cd4507e118af7c0d340fe7e2720f70976c4b75237dc"
,
"layers": [

"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 974,
"digest": "sha256:c04b14da8d1441880ed3fe6106fb2cc6fa1c9661846ac0266b8a5ec8edf37b7c"

]


根据上一步返回的Docker-Content-Digest删除,返回202表示删除成功
# curl -k -v -s -X DELETE http://localhost/v2/library/hello-world/manifests/sha256:a18ed77532f6d6781500db650194e0f9396ba5f05f8b50d4046b294ae5f83aa4

* Hostname was NOT found in DNS cache
* Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 80 (#0)
> DELETE /v2/library/hello-world/manifests/sha256:a18ed77532f6d6781500db650194e0f9396ba5f05f8b50d4046b294ae5f83aa4 HTTP/1.1
> User-Agent: curl/7.35.0
> Host: localhost
> Accept: */*
>
< **HTTP/1.1 202 Accepted**
* Server nginx/1.11.5 is not blacklisted
< Server: nginx/1.11.5
< Date: Wed, 23 Nov 2016 02:29:59 GMT
< Content-Type: text/plain; charset=utf-8
< Content-Length: 0
< Connection: keep-alive
< Docker-Distribution-Api-Version: registry/2.0
<
* Connection #0 to host localhost left intact

确认结果
# curl -X GET http://localhost/v2/library/hello-world/tags/list
"name":"library/hello-world","tags":null

删除镜像(hard delete)
在上一步中,只是删除了镜像的manifests信息,解引用的blob还在占用磁盘空间,执行如下命令可以查看可以删除的blob
docker exec -it myregistry_registry_1 /bin/registry garbage-collect --dry-run /etc/registry/config.yml

要删除blob,释放磁盘空间,需要执行下面的命令。需要特别注意的是在执行下面的命令时registry必须是只读模式(只读模式可在registry配置文件中设置),否则可能会导致数据不一致。
docker exec -it myregistry_registry_1 /bin/registry garbage-collect /etc/registry/

Docker Registry使用:公有Docker Registry使用私有Docker Registry的搭建

公有Docker Registry的操作

首先必须注册自己的dockerhub账号,假设为simpledockerhub

[[email protected] ]# docker login --默认即https://hub.docker.com

Username : simpledockerhub

Password: *****

Login Succeeded

[[email protected] ]# docker pull hello-world

[[email protected] ]# docker tag hello-world simpledockerhub/hello-world

[[email protected] ]#docker push simpledockerhub/hello-world     ------注意 /前面的名称必须是用户注册的用户名。

这样就把hello-world镜像上传到simpledockerhub用户下,使用docker pull命令就可以下载该镜像了

私有Docker Registry的搭建

1. 单机版:只能通过localhost操作(个人玩玩还行)

[[email protected] ]#  docker run -d -p 5000:5000 registry:2

[[email protected] ]#  docker tag hello-world localhost:5000/hello-world

[[email protected] ]#  docker push localhost:5000/hello-world

2.通过自签名证书方式联机访问(生产环境推荐使用该方案):

在主机上安装一个自签名的证书,并同时给需要访问寄存服务器的每个Docker 守护进程都安装一份。

Registry主机地址:10.76.64.63,  访问者地址:10.76.64.82

Registry主机10.76.64.63做如下操作:

1. 创建目录,存放证书文件:

[[email protected] ]# mkdir centos1_certs

2. 生成自签名证书,拷贝到 /etc/docker/certs.d/centos1:5000目录

[[email protected] ~]# openssl req -newkey rsa:4096 -nodes -sha256 -keyout centos1_certs/domain.key -x509 -days 365 -out centos1_certs/domain.crt
。。。
Common Name (eg, your name or your server‘s hostname) []:centos1    ---这个为主机名称,需要和/etc/hosts里对应上
。。。

[[email protected] ~]# mkdir -p /etc/docker/certs.d/centos1:5000

[[email protected] ~]# cp centos1_certs/domain.crt /etc/docker/certs.d/centos1:5000/domain.crt

3. 修改hosts文件

[[email protected] ~]#  vi /etc/hosts

10.76.64.63 centos1

4. 修改docker代理服务器文件(如果原来没有设置可以跳过)

[[email protected] ~]# vi /etc/systemd/system/docker.service.d/http-proxy.conf      --------该文件配置见:https://www.cnblogs.com/onetwothree/p/9371752.html

[Service]
Environment="NO_PROXY=127.0.0.1,localhost,centos1,10.76.*.*"

5. 重启服务

[[email protected] ~]# systemctl daemon-reload
[[email protected] ~]# systemctl restart docker.service

6. 启动registry V2

[[email protected] ~]# docker run -d --rm -p 5000:5000 --name registry -v /root/centos1_certs:/certs -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key docker.io/registry:2

7. 测试push命令

[[email protected] ]#  docker tag hello-world centos1:5000/hello-world

[[email protected] ~]# docker push centos1:5000/hello-world
The push refers to repository [centos1:5000/hello-world]
ee83fc5847cb: Pushed
latest: digest: sha256:aca41a608e5eb015f1ec6755f490f3be26b48010b178e78c00eac21ffbe246f1 size: 524

通过浏览器调用

技术分享图片

  到此为止可以通过主机名在本机访问registry了,如何在另外一台安装了docker环境的客户机访问registry呢?

8. 客户机10.76.64.82配置

直接访问:如下,报错是必然的

[[email protected] ~]# docker tag hello-world centos1:5000/hello-world:1.1
[[email protected] ~]# docker push centos1:5000/hello-world:1.1
The push refers to repository [centos1:5000/hello-world]
Get https://centos1:5000/v2/: Service Unavailable

解决步骤:

把centos1主机的domain.crt文件上传到客户机的centos1_certs目录,然后执行:

[[email protected] ~]# mkdir -p /etc/docker/certs.d/centos1:5000

[[email protected] ~]# cp centos1_certs/domain.crt /etc/docker/certs.d/centos1:5000/domain.crt

接下来执行上面的3、4、5步。

现在可以测试push命令了:

[[email protected] ~]# docker tag hello-world centos1:5000/helloworld
[[email protected] ~]# docker push centos1:5000/helloworld
The push refers to repository [centos1:5000/helloworld]
ee83fc5847cb: Mounted from hello-world
latest: digest: sha256:aca41a608e5eb015f1ec6755f490f3be26b48010b178e78c00eac21ffbe246f1 size: 524

 成功啦!

3.另外的方案:

对将要访问寄存服务器的所有Docker 守护进程加上-- insecure-registry ip或hostname:5000 参数,其中的地址和端口需要替换成你的服务器的信息,然后重新启动Docker 守护进程。

1. [[email protected] ~]#vi /etc/hosts

10.76.64.82 centosdocker

2. [[email protected] ~]# vi /lib/systemd/system/docker.service

....

OPTIONS=‘--selinux-enabled --insecure-registry centosdocker:5000‘      -----添加这一行
[Install]
WantedBy=multi-user.target

3. [[email protected] ~]# vi  /etc/docker/daemon.json

{"insecure-registries":["centosdocker:5000"] }

4. [[email protected] system]# systemctl daemon-reload
5. [[email protected] system]# systemctl restart docker.service
6. [[email protected] system]# docker run -d -p 5000:5000 registry:2

7. [[email protected] system]# docker tag hello-world centosdocker:5000/hello-world

8. [[email protected] system]# docker push centosdocker:5000/hello-world
The push refers to repository [centosdocker:5000/hello-world]
ee83fc5847cb: Pushed
latest: digest: sha256:aca41a608e5eb015f1ec6755f490f3be26b48010b178e78c00eac21ffbe246f1 size: 524

部署到客户机除了不需要[[email protected] system]# docker run -d -p 5000:5000 registry:2外,其他操作相同,有兴趣可以试一下,如果有代理的话,需要在docker的no_proxy配置项上添加上registry主机名,如:

[Service]
Environment="NO_PROXY=127.0.0.1,localhost,centos1,centosdocker,10.76.*.*"

 
























以上是关于如何搭建及使用docker registry的主要内容,如果未能解决你的问题,请参考以下文章

Docker搭建Redis Cluster集群及扩容和收容

Docker环境搭建及使用

Docker私有仓库的搭建及使用

Graylog 环境搭建及使用

如何使用 Weave 以及 Docker 搭建 Nginx 反向代理/负载均衡服务器

docker的搭建及使用