一、前言
官方的Docker hub是一个用于管理公共镜像的好地方,我们可以在上面找到我们想要的镜像,也可以把我们自己的镜像推送上去。但是,有时候,我们的使用场景需要我们拥有一个私有的镜像仓库用于管理我们自己的镜像。这个可以通过开源软件Registry来达成目的。
Registry在github上有两份代码:老代码库和新代码库。老代码是采用python编写的,存在pull和push的性能问题,出到0.9.1版本之后就标志为deprecated,不再继续开发。从2.0版本开始就到在新代码库进行开发,新代码库是采用go语言编写,修改了镜像id的生成算法、registry上镜像的保存结构,大大优化了pull和push镜像的效率。目前Docker Registry已经升级到了v2,最新版的Docker已不再支持v1。Registry v2使用Go语言编写,在性能和安全性上做了很多优化,重新设计了镜像的存储格式。
使用私有仓库有许多优点:
- 节省网络带宽,针对于每个镜像不用每个人都去中央仓库上面去下载,只需要从私有仓库中下载即可;
- 提供镜像资源利用,针对于公司内部使用的镜像,推送到本地的私有仓库中,以供公司内部相关人员使用。
环境准备
环境:两个装有Docker的Centos7虚拟机
虚拟机一:192.168.0.104 docker registry仓库
虚拟机二:192.168.0.107 registry客户端
1、可以连接互联网
2、添加 yum源
二、Registry的部署
1.安装相关依赖包
[root@registry-server ~]#yum install -y python-devel libevent-devel python-pip gcc xz-devel gcc-c++ openssl-devel
[root@registry-server ~]#pip install --upgrade pip
[root@registry-server ~]# pip install gunicorn pyyaml flask flask-cors rsa gevent
2.克隆docker-registry源码
[root@registry-server ~]# git clone https://github.com/docker/docker-registry.git
正克隆到 'docker-registry'...
remote: Counting objects: 7007, done.
remote: Total 7007 (delta 0), reused 0 (delta 0), pack-reused 7007
接收对象中: 100% (7007/7007), 1.69 MiB | 34.00 KiB/s, done.
处理 delta 中: 100% (4099/4099), done.
[root@registry-server ~]# cd docker-registry/
[root@registry-server docker-registry]# cp config/config_sample.yml config/config.yml #复制参考配置文件
[root@registry-server docker-registry]#vim config/config.yml #local段为本地仓库数据目录路径,按需修改
安装docker-registry
python setup.py install
报错,提示安装 M2Crypto的时候没有swig命令,经过测试解决方法为:
1.安装swig命令
[root@registry-server docker-registry]# tar xf swig-3.0.12.tar.gz
[root@registry-server docker-registry]# cd swig-3.0.12
[root@registry-server swig-3.0.12]# ./configure
......
[root@registry-server swig-3.0.12]# make &&make install
....
Installation complete
2.安装M2Crypto
[root@registry-server swig-3.0.12]# cd ..
[root@registry-server docker-registry]# tar xf M2Crypto-0.22.3.tar.gz
[root@registry-server docker-registry]# cd M2Crypto-0.22.3
[root@registry-server M2Crypto-0.22.3]# vim setup.py
添加本行代码 self.swig_opts.append('-cpperraswarn')
[root@registry-server M2Crypto-0.22.3]# python setup.py install
......
Finished processing dependencies for M2Crypto==0.22.3
3.安装registry
[root@registry-server M2Crypto-0.22.3]# cd ..
[root@registry-server docker-registry]# python setup.py install
......
Finished processing dependencies for docker-registry==1.0.0-dev
4.运行本地仓库
[root@registry-server docker-registry]# mkdir /var/log/docker-registry/ #创建日志目录
[root@registry-server docker-registry]# gunicorn --access-logfile /var/log/docker-registry/access.log --error-logfile /var/log/docker-registry/error.log -k gevent --max-requests 100 -t 3600 -b 127.0.0.1:5000 -w 1 docker_registry.wsgi:application &
[1] 54733
[root@registry-server docker-registry]# 14/Dec/2017:22:55:48 +0000 WARNING: Cache storage disabled!
14/Dec/2017:22:55:48 +0000 WARNING: LRU cache disabled!
14/Dec/2017:22:55:48 +0000 DEBUG: Will return docker-registry.drivers.file.Storage
[root@registry-server docker-registry]# netstat -tnlp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1035/sshd
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 2161/master
tcp 0 0 127.0.0.1:5000 0.0.0.0:* LISTEN 54733/python
tcp6 0 0 :::22 :::* LISTEN 1035/sshd
tcp6 0 0 ::1:25 :::* LISTEN 2161/master
[root@registry-server docker-registry]# curl http://127.0.0.1:5000 #
"\"docker-registry server\""
三、registry服务监听在本地,为了让其他主机访问,安装nginx,进行转发,并添加认证
1.创建https自建证书
[root@registry-server ~]# openssl genrsa -des3 -out my.key 1024 #生成一个RSA秘钥
Generating RSA private key, 1024 bit long modulus
...............................................................++++++
............++++++
e is 65537 (0x10001)
Enter pass phrase for my.key: #输入一个密码
Verifying - Enter pass phrase for my.key: #确认密码
[root@registry-server ~]# openssl rsa -in my.key -out nopass.key #拷贝一个不需要密码的秘钥文件
Enter pass phrase for my.key:
writing RSA key
[root@registry-server ~]# openssl req -new -key nopass.key -out my.csr
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) []:BJ
Locality Name (eg, city) [Default City]:BJ
Organization Name (eg, company) [Default Company Ltd]:LP
Organizational Unit Name (eg, section) []:LP
Common Name (eg, your name or your server's hostname) []:registry-server #自己的域名
Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
[root@registry-server ~]# openssl x509 -req -days 3650 -in my.csr -signkey nopass.key -out my.crt #创建自签证书
Signature ok
subject=/C=CN/ST=BJ/L=BJ/O=LP/OU=LP/CN=registry-server
Getting Private key
[root@registry-server ~]# mkdir /etc/ssl/private/ #创建秘钥存放目录
[root@registry-server ~]# cp my.* nopass.key /etc/ssl/private/ #拷贝到指定目录
[root@registry-server ~]# ll /etc/ssl/private/
总用量 16
-rw-r--r--. 1 root root 814 12月 14 23:01 my.crt
-rw-r--r--. 1 root root 635 12月 14 23:01 my.csr
-rw-r--r--. 1 root root 963 12月 14 23:01 my.key
-rw-r--r--. 1 root root 887 12月 14 23:01 nopass.key
2.安装及配置nginx
[root@registry-server ~]# yum install nginx httpd -y #安装nginx和httpd
[root@registry-server ~]# htpasswd -c /etc/nginx/docker-registry-htpasswd user1 #创建第一个用户
New password:
Re-type new password:
Adding password for user user1
[root@registry-server ~]# htpasswd /etc/nginx/docker-registry-htpasswd user2 #创建第二个用户,注意没有 -c 参数
New password:
Re-type new password:
Adding password for user user2
编辑配置文件
[root@registry-server ~]# vim /etc/nginx/conf.d/docker-registry.conf
upstream docker-registry {
server 127.0.0.1:5000;
}
server {
listen 192.168.0.104:5000;
#listen 192.168.0.104:80;
server_name www.docker-registry.com;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
client_max_body_size 0;
chunked_transfer_encoding on;
ssl on;
ssl_certificate /etc/ssl/private/my.crt;
ssl_certificate_key /etc/ssl/private/nopass.key;
ssl_protocols TLSv1.1 TLSv1.2;
location / {
auth_basic "please Input username/password";
auth_basic_user_file /etc/nginx/docker-registry-htpasswd;
proxy_pass http://docker-registry;
}
location /_ping {
auth_basic off;
proxy_pass http://docker-registry;
}
location /v1/_ping {
auth_basic off;
proxy_pass http://docker-registry;
}
}
[root@registry-server ~]# setenforce 0
[root@registry-server ~]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@registry-server conf.d]# systemctl restart nginx
View Code
客户端测试:
1.配置hosts解析
[root@registry-client ~]# echo "192.168.0.104 www.docker-registry.com" >> /etc/hosts
[root@registry-client ~]# cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.0.104 www.docker-registry.com
2.不使用用户名密码和使用用户名密码的结果
直接访问
[root@registry-client ~]# curl --insecure https://www.docker-registry.com:5000 #不添加--insecure参数,会产生报错,原因是自签发证书未经认证,无法识别。
<html>
<head><title>401 Authorization Required</title></head>
<body bgcolor="white">
<center><h1>401 Authorization Required</h1></center>
<hr><center>nginx/1.12.2</center>
</body>
</html>
带用户名和密码访问
[root@registry-client ~]# curl --insecure https://user1:123456@www.docker-registry.com:5000
"\"docker-registry server\""
四、.下载、上传测试镜像
服务端:
[root@registry-server ~]# docker pull hello-world
Using default tag: latest
Trying to pull repository docker.io/library/hello-world ...
latest: Pulling from docker.io/library/hello-world
ca4f61b1923c: Pull complete
Digest: sha256:be0cd392e45be79ffeffa6b05338b98ebb16c87b255f48e297ec7f98e123905c
给测试镜像打tag #tag命令可以为以存在的重复命名,并不执行重命名,而是保留原有命名基础上,添加一个新的名称,看上去像新添加了一个image
[root@registry-server ~]# docker tag hello-world 127.0.0.1:5000/hello-world
查看本地镜像
[root@registry-server ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/registry 2 177391bcf802 4 days ago 33.26 MB
127.0.0.1:5000/hello-world latest f2a91732366c 2 weeks ago 1.848 kB
docker.io/hello-world latest f2a91732366c 2 weeks ago 1.848 kB
push测试镜像到私有仓库
[root@registry-server ~]# docker push 127.0.0.1:5000/hello-world
The push refers to a repository [127.0.0.1:5000/hello-world]
f999ae22f308: Image successfully pushed
Pushing tag for rev [f2a91732366c] on {http://127.0.0.1:5000/v1/repositories/hello-world/tags/latest}
客户端:
登录registry:
[root@registry-client ~]# docker login www.docker-registry.com:5000
Username : user1
Password:
Login Succeeded
查看registry信息:
[root@registry-client ~]# curl --insecure https://user1:123456@www.docker-registry.com:5000/v1/search
{"num_results": 1, "query": "", "results": [{"description": "", "name": "library/hello-world"}]}# 可以看到hello-world镜像在library下
搜索指定镜像:
[root@registry-client ~]# curl --insecure https://user1:123456@www.docker-registry.com:5000/v1/search?q=hello-world
{"num_results": 1, "query": "hello-world", "results": [{"description": "", "name": "library/hello-world"}]}
可以看到hello-world在library/hello-world下
客户端下载:
[root@registry-client ~]# docker pull www.docker-registry.com:5000/library/hello-world #下载到客户端
Using default tag: latest
Trying to pull repository www.docker-registry.com:5000/library/hello-world ...
Pulling repository www.docker-registry.com:5000/library/hello-world
f2a91732366c: Pull complete Status: Downloaded newer image for www.docker-registry.com:5000/library/hello-world:latest
www.docker-registry.com:5000/library/hello-world: this image was pulled from a legacy registry. Important: This registry version will not be supported in future versions of docker.
[root@registry-client ~]# docker images #查看下载的镜像
REPOSITORY TAG IMAGE ID CREATED SIZE
www.docker-registry.com:5000/library/hello-world latest 1cd4a767e1b4 3 weeks ago 1.848 kB
"一劳永逸" 的话,有是有的,而 "一劳永逸" 的事却极少