自定义的镜像可以通过公有仓库进行管理,也可以搭建一个本地的私有仓库进行管理。

1.运行环境

  • OS:centos7
  • docker-reistry1.0 下载registry.tar
  • nginx1.10.2
  • docker1.8.2

2.使用docker-registry搭建私有仓库

将registry.tar上传到安装了docker的centos7中,导入nginx镜像。

1
2
3
4
[root@localhost ~]# docker load < registry.tar
[root@registry ~]# docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
docker.io/registry latest 07d93e41c370 13 months ago 422.8 MB

修改所有计算节点的的hosts配置文件,并刷新hostname。

1
2
3
4
[root@localhost ~]# vi /etc/hosts
192.168.147.130 registry
192.168.147.130 registry_private
[root@localhost ~]# hostname -F /etc/hostname(刷新hostname)

在docker配置文件中添加允许连接镜像仓库:

1
2
[root@localhost ~]# vi /etc/sysconfig/docker
OPTIONS='--insecure-registry registry:5000 --insecure-registry registry_private:5001

重启docker:

1
[root@localhost ~]# service docker restart

运行镜像仓库:

1
2
3
4
5
[root@localhost ~]# docker run -d -p 5000:5000 --name=registry --restart=always --privileged=true --log-driver=none -v /home/data/registrydata:/tmp/registry registry
03859903eb0322eaa7b29a915737bb22b685c466d020da499d491485c1f67307
[root@registry ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
03859903eb03 registry "docker-registry" About an hour ago Up 45 minutes 0.0.0.0:5000->5000/tcp registry

上传镜像到仓库:

1
2
3
4
5
6
7
8
9
10
[root@localhost ~]# docker tag sshd:centos registry:5000/sshd:centos
[root@localhost ~]# docker push registry:5000/sshd:centos
The push refers to a repository [registry:5000/sshd] (len: 1)
Sending image list
Pushing repository registry:5000/sshd (1 tags)
9509659cbefb: Image successfully pushed
f0efe62f33e4: Image successfully pushed
Pushing tag for rev [f0efe62f33e4] on {http://registry:5000/v1/repositories/sshd/tags/centos}
[root@localhost ~]# curl registry:5000/v1/search
{"num_results": 1, "query": "", "results": [{"description": "", "name": "library/sshd"}]}

下载镜像到本地:

1
2
3
4
[root@registry ~]# docker pull registry:5000/sshd:centos
f0efe62f33e4: Download complete
9509659cbefb: Download complete
Status: Image is up to date for registry:5000/sshd:centos

3.为私有仓库添加用户认证

registry没有安全权限的设置,除非防火墙限制,否则任何人都可以pull、push镜像到registry。更安全的做法是在外层加入登录认证机制。可以使用nginx做反向代理,为私有仓库添加用户认证。

3.1安装及配置nginx

安装nginx

1
[root@registry ~]# yum install nginx

安装htpasswd工具,生成加密后的密码,并将用户名和密码存储在本地指定路径的文件中。

1
2
3
4
5
6
7
[root@registry ~]# git clone git://github.com/http-auth/htpasswd.git
[root@registry ~]# npm install -g htpasswd
[root@registry ~]# npm install -g htpasswd
[root@registry ~]# htpasswd -c /etc/nginx/docker-registry.htpasswd usr1
New password:
Re-type new password:
Adding password for user usr1.

配置nginx:在/etc/nginx/sites-enabled/目录下添加新的站点配置文件docker-registry:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
[root@registry nginx]# mkdir /etc/nginx/sites-enabled/
[root@registry nginx]# vi /etc/nginx/sites-enabled/docker-registry
upstream docker-registry {
server localhost:5000;
}
server {
listen 5001;
server_name registry_private;
proxy_set_header Host $http_host; # required for Docker client sake
proxy_set_header X-Real-IP $remote_addr; # pass on real client IP
client_max_body_size 0; # disable any limits to avoid HTTP 413 for large image uploads
# required to avoid HTTP 411: see Issue #1486 (https://github.com/dotcloud/docker/issues/1486)
chunked_transfer_encoding on;
location / {
# let Nginx know about our auth file
auth_basic "Restricted";
auth_basic_user_file 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;
}
}

建立配置文件软连接,放在/etc/nginx/conf.d/下,让nginx启用它,然后重启nginx服务:

1
2
[root@registry sites-enabled]# sudo ln -s /etc/nginx/sites-enabled/docker-registry /etc/nginx/conf.d/docker-registry.conf
[root@registry sites-enabled]# service nginx restart

如果这一步遇到这个问题:

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@registry sites-enabled]# systemctl status nginx.service
nginx.service - The nginx HTTP and reverse proxy server
Loaded: loaded (/usr/lib/systemd/system/nginx.service; disabled)
Active: failed (Result: exit-code) since Thu 2017-03-02 11:08:27 CST; 14s ago
Process: 39831 ExecStartPre=/usr/sbin/nginx -t (code=exited, status=1/FAILURE)
Process: 39830 ExecStartPre=/usr/bin/rm -f /run/nginx.pid (code=exited, status=0/SUCCESS)
Mar 02 11:08:27 registry systemd[1]: Starting The nginx HTTP and reverse proxy server...
Mar 02 11:08:27 registry nginx[39831]: nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
**Mar 02 11:08:27 registry nginx[39831]: nginx: [emerg] bind() to 0.0.0.0:5001 failed (13: Permission denied)**
Mar 02 11:08:27 registry nginx[39831]: nginx: configuration file /etc/nginx/nginx.conf test failed
Mar 02 11:08:27 registry systemd[1]: nginx.service: control process exited, code=exited status=1
Mar 02 11:08:27 registry systemd[1]: Failed to start The nginx HTTP and reverse proxy server.
Mar 02 11:08:27 registry systemd[1]: Unit nginx.service entered failed state.

可能是是开启了selinux导致的,查看是否开启了selinux,”Enforecing”代表开启了selinux,”disabled”或者”permissive”则是关闭了。

1
2
3
4
5
[root@registry sites-enabled]# getenforce
Enforcing
[root@registry sites-enabled]# setenforce 0 (临时关闭selinux)
[root@registry sites-enabled]# getenforce
Permissive

这时访问registry_private:5001,则被禁止:

1
2
[root@registry sites-enabled]# getenforce
Permissive

临时修改重启电脑后再重启nginx,每次均需要修改,可以永久关闭,修改/etc/selinux/config 文件,将SELINUX=enforcing改为SELINUX=disabled,重启电脑生效。
通过用户名和密码登录:

1
2
[root@registry sites-enabled]# curl usr1:123456@registry_private:5001/v1/search
{"num_results": 1, "query": "", "results": [{"description": "", "name": "library/sshd"}]}

如果用浏览器登录,则会出现要求填写用户名和密码的对话框。

3.2为nginx安装ssl证书

此时登录registry_private下载镜像,会无法下载:

1
2
3
4
5
6
7
8
9
[root@registry sites-enabled]# docker login registry_private:5001
Username: usr1
Password:
Email:
WARNING: login credentials saved in /root/.docker/config.json
Login Succeeded
[root@registry sites-enabled]# docker pull registry_private:5001/sshd:centos
Trying to pull repository registry_private:5001/sshd ... failed
Could not reach any registry endpoint

这是因为docker-registry不允许http明文传输,此时可以安装SSL证书,使用HTTPS传输。
首先在nginx配置文件中添加:

1
2
3
4
5
6
7
8
9
[root@registry sites-enabled]# vi /etc/nginx/conf.d/docker-registry.conf
......
server {
listen 5001;
server_name registry_private;
ssl on;
ssl_certificate /etc/nginx/ssl/nginx.crt;
ssl_certificate_key /etc/nginx/ssl/nginx.key;
......

创建相关证书:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[root@registry sites-enabled]# mkdir /etc/nginx/ssl (创建配置目录)
[root@registry sites-enabled]# cd /etc/pki/CA
[root@registry CA]# openssl genrsa -out private/cakey.pem 2048 (生成秘钥)
[root@registry CA]# cd /etc/pki/CA/private/
y.pem
[root@registry private]# chmod 400 cakey.pem (修改私钥文件权限)[root@registry private]# cd /etc/pki/CA/
[root@registry CA]# openssl req -new -x509 -key private/cakey.pem -out cacert.pem (生成根证书)
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]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:
Email Address []:

生成根证书的时候会提示输入一些内容,可以随便输入,也可直接回车。如果有入,最好与后续为nginx生成证书签署请求的填写内容保持一致。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
[root@registry private]# cd /etc/pki/CA/
[root@registry CA]# openssl req -new -x509 -key private/cakey.pem -out cacert.pem (生成根证书)
[root@registry CA]# cd /etc/nginx/ssl
[root@registry ssl]# openssl genrsa -out nginx.key 2048 (为nginx web服务器生成ssl密钥)
[root@registry ssl]# openssl req -new -key nginx.key -out nginx.csr (为nginx生成证书请求)
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]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:regstry_private(**此处一定要填写需要授予证书的服务器域名或主机名**)
Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
[root@registry ssl]# touch /etc/pki/CA/index.txt
[root@registry ssl]# touch /etc/pki/CA/serial
[root@registry ssl]# echo "00" > /etc/pki/CA/serial
[root@registry ssl]# openssl ca -in nginx.csr -out nginx.crt (私有CA根据请求来签发证书)
Using configuration from /etc/pki/tls/openssl.cnf
Check that the request matches the signature
Signature ok
The commonName field needed to be supplied and was missing (生成证书请求是没有填写任何信息,所以有这一句话的提示。)

让根证书起作用:

1
2
[root@registry ssl]# cp /etc/pki/tls/certs/ca-bundle.crt{,.bak} (备份,以防出错)
[root@registry ssl]# cat /etc/pki/CA/cacert.pem >> /etc/pki/tls/certs/ca-bundle.crt

此时再下载私有仓库的镜像:

1
2
3
4
[root@registry certs]# docker pull registry_private:5001/sshd:centos
f0efe62f33e4: Download complete
9509659cbefb: Download complete
Status: Image is up to date for registry_private:5001/sshd:centos

用网页登录时,需要注意是https协议。
网页登录

注意:下载不在同一主机上的私有仓库时,需要在docker的配置文件中添加 –insecurity-registry 参数。

参考博客:
https://segmentfault.com/a/1190000000801162
http://cloud.51cto.com/art/201412/458680_all.htm