一、什么是私有仓库:
- 仓库是集中存放镜像文件的场所。有时候会把仓库和仓库注册服务器(Registry)混为一谈,并不严格区分。实际上,仓库注册服务器上往往存放着多个仓库,每个仓库中又包含了多个镜像,每个镜像有不同的标签(tag)。
- 仓库分为公开仓库(Public)和私有仓库(Private)两种形式。最大的公开仓库是 Docker Hub,存放了数量庞大的镜像供用户下载。 国内的公开仓库包括 Docker Pool等,可以提供大陆用户更稳定快速的访问。
- 当然,用户也可以在本地网络内创建一个私有仓库。当用户创建了自己的镜像之后就可以使用 push 命令将它上传到公有或者私有仓库,这样下次在另外一台机器上使用这个镜像时候,只需要从仓库上 pull 下来就可以了。
二、私有仓库的优势:
- 有时候使用Docker Hub这样的公共仓库可能不方便,这种情况下用户可以使用registry创建一个本地仓库供私人使用,
这点跟Maven的管理类似。 - 使用私有仓库有许多优点:
1)节省网络带宽,针对于每个镜像不用每个人都去中央仓库上面去下载,只需要从私有仓库中下载即可;
2)提供镜像资源利用,针对于公司内部使用的镜像,推送到本地的私有仓库中,以供公司内部相关人员使用。 - 目前Docker Registry已经升级到了v2,最新版的Docker已不再支持v1。Registry v2使用Go语言编写,在性能和安全性上做了很多优化,重新设计了镜像的存储格式。如果需要安装registry v2,只需下载registry:2.2即可。
- Docker官方提供的工具docker-registry可以用于构建私有的镜像仓库。
三、如何搭建私有仓库
- 第一种用docker命令拉取docker registry,将docker的仓库镜像拉取到本地,在本地构建一个docker仓库,这种方法要自己对仓库进行权限管理,没有图形化页面操作,命令操作比较繁琐,另外在dockertoolbox下搭建私有镜像库出现的问题比较多,建议还是安装linux系统进行搭建。
- 第二种集成harbor,docker-compose可以进行图形化页面仓库以及图形化权限管理,harbor也集成了mysql和log。
我们今天就先来讲一下registory私有仓库的搭建
四、Registry私有仓库的搭建
Registry工作原理
一次docker pull 或 push背后发生的事情
index服务主要提供镜像索引以及用户认证的功能。当下载一个镜像的时候,首
先会去index服务上做认证,然后查找镜像所在的registry的地址并放回给
docker客户端,docker客户端再从registry下载镜像,在下载过程中 registry会
去index校验客户端token的合法性,不同镜像可以保存在不同的registry服务上,
其索引信息都放在index服务上。
Docker Registry有三个角色,分别是index、registry和registry client。
-
index
负责并维护有关用户帐户、镜像的校验以及公共命名空间的信息。
Web UI
元数据存储
认证服务
符号化 -
registry
是镜像和图表的仓库,它不具有本地数据库以及不提供用户认证,
通过Index Auth service的Token的方式进行认证。 -
Registry Client
Docker充当registry客户端来维护推送和拉取,以及客户端的授权。
1.下载registry镜像
这里的虚拟机一定要能上网才可以
2.运行容器
3.上传localhost:5000/nginx(镜像随便选,但是必须得是本地localhost或者localhost:5000)
首先我们给nginx镜像的的标签设置为localhost:5000/nginx,本地镜像在命名时需要加上仓库的ip和端口[root@server1 ~]# docker tag nginx:latest localhost:5000/nginx
[root@server1 ~]# docker images localhost:5000/nginx
REPOSITORY TAG IMAGE ID CREATED SIZE
localhost:5000/nginx latest 53f3fd8007f7 3 weeks ago 109MB
然后上传镜像到我们的私有仓库中[root@server1 ~]# docker push localhost:5000/nginx The push refers to repository [localhost:5000/nginx] 332fa54c5886: Pushed 6ba094226eea: Pushed 6270adb5794c: Pushed latest: digest: sha256:e770165fef9e36b990882a4083d8ccf5e29e469a8609bb6b2e3b47d9510e2c8d size:948
安装tree,查看/opt/registry目录中的镜像数据
[root@server1 ~]# yum install -y tree
[root@server1 ~]# cd /opt/registry/
[root@server1 registry]# ls
docker
[root@server1 registry]# tree docker/
docker/
└── registry
└── v2
├── blobs
│ └── sha256
│ ├── 53
│ │ └── 53f3fd8007f76bd23bf663ad5f5009c8941f63828ae458cef584b5f85dc0a7bf
│ │ └── data
│ ├── 68
│ │ └── 688a776db95ffbd66dd4696263d34ca00bd330f30f39a9d39d818a07b086ed17
│ │ └── data
│ ├── 6b
│ │ └── 6bfc4ec4420a10145bd40caf0499a57618342f27c0ad95f1785b8a1e31090058
│ │ └── data
│ ├── 74
│ │ └── 743f2d6c1f65c793009f30acb07845ba2ef968192732afdab2ecf9a475515393
│ │ └── data
│ └── e7
│ └── e770165fef9e36b990882a4083d8ccf5e29e469a8609bb6b2e3b47d9510e2c8d
│ └── data
└── repositories
└── nginx
├── _layers
│ └── sha256
│ ├── 53f3fd8007f76bd23bf663ad5f5009c8941f63828ae458cef584b5f85dc0a7bf
│ │ └── link
│ ├── 688a776db95ffbd66dd4696263d34ca00bd330f30f39a9d39d818a07b086ed17
│ │ └── link
│ ├── 6bfc4ec4420a10145bd40caf0499a57618342f27c0ad95f1785b8a1e31090058
│ │ └── link
│ └── 743f2d6c1f65c793009f30acb07845ba2ef968192732afdab2ecf9a475515393
│ └── link
├── _manifests
│ ├── revisions
│ │ └── sha256
│ │ └── e770165fef9e36b990882a4083d8ccf5e29e469a8609bb6b2e3b47d9510e2c8d
│ │ └── link
│ └── tags
│ └── latest
│ ├── current
│ │ └── link
│ └── index
│ └── sha256
│ └── e770165fef9e36b990882a4083d8ccf5e29e469a8609bb6b2e3b47d9510e2c8d
│ └── link
└── _uploads
33 directories, 12 files
我们发现我们上传的nginx镜像已经在我们的私有仓库里了,而且其镜像数据是分层的
4.从私有仓库下载镜像
在下载之前我们要先获取registry仓库有的镜像
[root@server1 registry]# curl http://localhost:5000/v2/_catalog
{"repositories":["nginx"]}
获取某个镜像的标签列表
[root@server1 registry]# curl http://172.25.66.1:5000/v2/nginx/tags/list
{"name":"nginx","tags":["latest"]}
我们先删除之前的镜像,这样有利于我们看到结果
[root@server1 registry]# docker rmi nginx:latest
[root@server1 registry]# docker rmi localhost:5000/nginx:latest
下载
[root@server1 registry]# docker pull localhost:5000/nginx
Using default tag: latest
latest: Pulling from nginx
Digest: sha256:e770165fef9e36b990882a4083d8ccf5e29e469a8609bb6b2e3b47d9510e2c8d
Status: Downloaded newer image for localhost:5000/nginx:latest
[root@server1 registry]# docker images localhost:5000/nginx
REPOSITORY TAG IMAGE ID CREATED SIZE
localhost:5000/nginx latest 53f3fd8007f7 3 weeks ago 109MB
[root@server1 registry]# docker tag localhost:5000/nginx:latest nginx
[root@server1 registry]# docker images nginx
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 53f3fd8007f7 3 weeks ago 109MB
[root@server1 registry]#
5.配置私有仓库rejstry的加密访问控制
a.创建certs证书,生成服务器私钥
[root@server1 registry]# cd /tmp/docker/
[root@server1 docker]# mkdir certs #创建证书的存放位置
[root@server1 docker]# openssl req -newkey rsa:4096 -nodes -sha256 -keyout certs/redhat.org.key -x509 -days 365 -out certs/redhat.org.crt
Generating a 4096 bit RSA private key
..............................................++
......++
writing new private key to 'certs/redhat.org.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:cn
State or Province Name (full name) []:shaanxi
Locality Name (eg, city) [Default City]:xi'an
Organization Name (eg, company) [Default Company Ltd]:xupt
Organizational Unit Name (eg, section) []:linux
Common Name (eg, your name or your server's hostname) []:redhat.org #这里的域名必须和前面的一样
Email Address []:ljz@redhat.org
b.写入本地解析
[root@server1 docker]# cd certs/
[root@server1 certs]# ls
redhat.org.crt redhat.org.key
[root@server1 certs]# vim /etc/hosts
c.重新启动仓库
[root@server1 certs]# docker rm -f registry 删除之前的仓库
registry
[root@server1 certs]# docker run -d \
> --restart=always \ 设置容器启动策略
> --name registry \
> -v /tmp/docker/certs:/certs \ 挂载密钥
> -e REGISTRY_HTTP_ADDR=0.0.0.0:443 \ 设置仓库主机地址格式
> -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/redhat.org.crt \ 设置环境变量告诉容器证书的位置
> -e REGISTRY_HTTP_TLS_KEY=/certs/redhat.org.key \ 设置环境变量告诉容器私钥的位置
> -p 443:443 \
> -v /opt/registry:/var/lib/registry \
> registry:2
ad0d94c6b97223ca5759b1107adbf0dc089cb8653cf2d38e4836a4aec657c10a
d.将serts证书放到我们的docker数据目录
[root@server1 certs]# cd /etc/docker/
[root@server1 docker]# mkdir certs.d
[root@server1 docker]# cd certs.d/
[root@server1 certs.d]# mkdir redhat.org
[root@server1 certs.d]# cd redhat.org/
[root@server1 redhat.org]# cp /tmp/docker/certs/redhat.org.crt ca.crt
[root@server1 redhat.org]# ls
ca.crt
e.修改镜像标签(以我们之前的game2048为例)
f.上传镜像
[root@server1 ~]# docker push redhat.org/game2048
The push refers to repository [redhat.org/game2048]
88fca8ae768a: Pushed
6d7504772167: Pushed
192e9fad2abc: Pushed
36e9226e74f8: Pushed
011b303988d2: Pushed
latest: digest: sha256:8a34fb9cb168c420604b6e5d32ca6d412cb0d533a826b313b190535c03fe9390 size: 1364
6.客户端测试(server2)
a.安装dokcer
b.启动dokcer
[root@server2 docker]# systemctl start docker
c.创建证书的放置目录
[root@server2 docker]# cd /etc/docker/
[root@server2 docker]# ls
key.json
[root@server2 docker]# mkdir -p certs.d/redhat.org
[root@server2 docker]# ls
certs.d key.json
[root@server2 docker]# cd certs.d/redhat.org/
d.将server1的证书同步过来
[root@server1 ~]# cd /etc/docker/certs.d/redhat.org/
[root@server1 redhat.org]# ls
ca.crt
[root@server1 redhat.org]# scp ca.crt server2:/etc/docker/certs.d/redhat.org/
root@server2's password:
ca.crt 100% 2090 2.0KB/s 00:00
[root@server2 redhat.org]# ls
ca.crt
e.添加域名解析
vim /etc/hosts
f.测试:下载game2048
7.通过基本的身份认证是喜爱年私有仓库registry加密访问控制
a.创建certs证书,前面我们已经做过了,这里就不再做了
b.生成鉴权密码文件
[root@server1 ~]# cd /tmp/docker/
[root@server1 docker]# mkdir auth
[root@server1 docker]# docker run --rm --entrypoint htpasswd registry:2 -Bbn ljz redhat > auth/htpasswd 在这里设置用户为ljz,密码redhat
–entrypoint string:覆盖镜像默认的ENTRYPOINT,之前我们说过,ENTRYPOINT是不可以被覆盖的,如果实在要覆盖需要使用此参数
-B:强制密码加密
-b:使用命令行中的密码而不是提示输入密码
-n:不更新加密文件,只将加密后的用户名密码显示在屏幕上
[root@server1 docker]# cat auth/htpasswd
ljz:$2y$05$e9qrYky18OizOdcOA7.u/uvgVANtShRhw1TNvlEGoRg1XoSGs5.PG
c.删除之前的仓库,避免冲突
d.启动容器
[root@server1 docker]# docker run -d \
> --restart=always \
> --name registry \
> -v "$(pwd)"/certs:/certs \
> -e REGISTRY_HTTP_ADDR=0.0.0.0:443 \
> -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/redhat.org.crt \
> -e REGISTRY_HTTP_TLS_KEY=/certs/redhat.org.key \
> -p 443:443 \
> -v /opt/registry:/var/lib/registry \
> -v "$(pwd)"/auth:/auth \
> -e "REGISTRY_AUTH=htpasswd" \
> -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
> -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
> registry:2
35209b2037466455af972f48432e2ce6e93252751adf2bbf9008043ed440a4aa
e.测试:首先不登陆,直接上传镜像
[root@server1 docker]# docker tag ubuntu:latest redhat.org/ubuntu
[root@server1 docker]# docker push redhat.org/ubuntu
The push refers to repository [redhat.org/ubuntu]
5f70bf18a086: Preparing
11083b444c90: Preparing
9468150a390c: Preparing
56abdd66ba31: Preparing
no basic auth credentials
f.登陆上传
发现登陆后即可正常上传
g.查看认证文件,这是第一次登陆后自动生成的,下次就可以不用再登陆了