自建Docker Registry

前言

使用docker官方的registry下载镜像速度很慢,下载一次push到自己的搭建的registry中,再使用时就方便很多了,下面就是自己搭建私有registry的过程,记录一下。

环境

主机:10.1.1.40
OS:CentOS 7.3
Dokcer:1.12.6
Nginx:1.10.3
Registry:V2,容器化

# 搜索50个星以上的镜像,从描述可以看出已经是V2版本了
docker search --filter=stars=50 registry
INDEX       NAME                                              DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
docker.io   docker.io/registry                                The Docker Registry 2.0 implementation for...   1369      [OK]       
docker.io   docker.io/konradkleine/docker-registry-frontend   Browse and modify your Docker registry in ...   140                  [OK]
docker.io   docker.io/atcol/docker-registry-ui                A web UI for easy private/local Docker Reg...   88                   [OK]
docker.io   docker.io/hyper/docker-registry-web               Web UI, authentication service and event r...   79                   [OK]

# 下载官方的registry镜像
dokcer pull docker.io/registry

registry的默认配置文件为/etc/docker/registry/config.yml,image默认存放位置为/var/lib/registry/,通过卷保存在本地存储上

# 建立目录
mkdir -pv /mydata/registry/{conf,data}

# 建立配置文件
vim /mydata/registry/conf/config.yml
version: 0.1
log:
  fields:
    service: registry
storage:
  cache:
    blobdescriptor: inmemory
  filesystem:
    rootdirectory: /var/lib/registry
http:
  addr: :5000
  secret: admin
  headers:
    X-Content-Type-Options: [nosniff]
health:
  storagedriver:
    enabled: true
    interval: 10s
    threshold: 3

# 启动容器
docker run -d -p 4000:5000 --restart=always --name registry \
  -v /mydata/registry/conf/config.yml:/etc/docker/registry/config.yml \
  -v /mydata/registry/data:/var/lib/registry \
  docker.io/registry:latest


# 查看容器
docker ps 
CONTAINER ID        IMAGE                       COMMAND                  CREATED             STATUS              PORTS                    NAMES
7350a38dc313        docker.io/registry:latest   "/entrypoint.sh /etc/"   19 seconds ago      Up 18 seconds       0.0.0.0:4000->5000/tcp   registry

接下来,把下载下来的registry镜像push到私有的repository中

# 查看images
docker images
REPOSITORY                       TAG                 IMAGE ID            CREATED             SIZE
docker.io/registry               latest              047218491f8c        9 days ago          33.17 MB


# 给image打tag
docker tag 047218491f8c 10.1.1.40:4000/registry:v2

# push
docker push 10.1.1.40:4000/registry:v2
The push refers to a repository [10.1.1.40:4000/registry]
Get https://10.1.1.40:4000/v1/_ping: http: server gave HTTP response to HTTPS client

push的时候报错了。自建v2版的registry需要启用TLS认证,否则就会报错。
如果本地安装registry,可以通过修改配置文件/etc/sysconfig/docker加上INSECURE_REGISTRY='--insecure-registry 10.1.1.40:4000'来解决,registry容器化后,没有/etc/sysconfig/docker,只能使用TLS证书来解决。

生成自签名证书

# 创建ssl目录
mkdir -p /etc/ssl

# 生成证书

cd /etc
openssl req -newkey rsa:4096 -nodes -sha256 -keyout ssl/ivixq.com.key -x509 -days 365 -out ssl/ivixq.com.crt

Generating a 4096 bit RSA private key
......................++
..........................................................................................++
writing new private key to 'ssl/ivixq.com.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) []:GD
Locality Name (eg, city) [Default City]:GZ
Organization Name (eg, company) [Default Company Ltd]:IV
Organizational Unit Name (eg, section) []:IV
Common Name (eg, your name or your server's hostname) []:registry.ivixq.com
Email Address []:admin@ivixq.com

# 证书和私钥文件

ll ssl/
total 8
-rw-r--r-- 1 root root 2074 Mar 13 10:14 ivixq.com.crt
-rw-r--r-- 1 root root 3272 Mar 13 10:14 ivixq.com.key

重新启动容器

# 删除刚才启动的registry,加上REGISTRY_HTTP_TLS_CERTIFICATE、REGISTRY_HTTP_TLS_KEY环境变量,支持证书

docker rm -f registry
docker run -d -p 4000:5000 --restart=always --name registry \
  -v /mydata/registry/conf/config.yml:/etc/docker/registry/config.yml \
  -v /mydata/registry/data:/var/lib/registry \
  -v /etc/ssl:/certs \
  -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/ivixq.com.crt \
  -e REGISTRY_HTTP_TLS_KEY=/certs/ivixq.com.key \
  docker.io/registry:latest

# 证书不支持IP地址,必须使用域名进行申请,故签名域名为registry.ivixq.com,编辑/etc/hosts文件,添加域名解析

vim /etc/hosts
10.1.1.40    registry.ivixq.com

# registry打tag,并push

docker tag 047218491f8c registry.ivixq.com:4000/registry

docker push registry.ivixq.com:4000/registry
The push refers to a repository [registry.ivixq.com:4000/registry]
Get https://registry.ivixq.com:4000/v1/_ping: x509: certificate signed by unknown authority

又有报错信息Get https://registry.ivixq.com:4000/v1/_ping: x509: certificate signed by unknown authority,docker client认为registry传过来证书由一个未知的授权机构签署的证书,验证失败。
解决方法:
为docker client安装证书,前面我们创建了自签名证书,将自签名的证书拷贝到docker client目录的下/etc/docker/certs.d/

注意:存放证书的文件夹名称必须是证书中的域名+registry的端口号

# 建立目录

mkdir -pv /etc/docker/certs.d/registry.ivixq.com:4000

# 拷贝证书

cp /etc/ssl/ivixq.com.crt /etc/docker/certs.d/registry.ivixq.com:4000/ivixq.com.crt

# 重启docker

systemctl restart docker

# 再次push

docker push registry.ivixq.com:4000/registry
The push refers to a repository [registry.ivixq.com:4000/registry]
0912b310db10: Pushed 
6767cac03a2d: Pushed 
f38182d44088: Pushed 
b5aac7bb5fdf: Pushed 
9f8566ee5135: Pushed 
latest: digest: sha256:437df2cf9a6553a91552f716e7b51f696e98aae6e961bf74e113b0363e913480 size: 1364

终于push成功了。

注意:其他docker主机要使用这个自建registry,也需要为docker client导入证书

在其他HOST使用自建registry

# 在其他host上直接pull,会发生报错

docker pull 10.1.1.40:4000/registry:v2
Trying to pull repository 10.1.1.40:4000/registry ... 
Get https://10.1.1.40:4000/v1/_ping: x509: cannot validate certificate for 10.1.1.40 because it doesn't contain any IP SANs

# 添加域名解析,再pull,还会报错

vim /etc/hosts
10.1.1.40    registry.ivixq.com

docker pull registry.ivixq.com:4000/registry:v2
Trying to pull repository registry.ivixq.com:4000/registry ... 
Get https://registry.ivixq.com:4000/v1/_ping: x509: certificate signed by unknown authority

# 添加证书,重启docker服务后,再pull,成功

mkdir -pv /etc/docker/certs.d/registry.ivixq.com:4000

scp /etc/docker/certs.d/registry.ivixq.com\:4000/ivixq.com.crt root@10.1.1.50:/etc/docker/certs.d/registry.ivixq.com\:4000/

systemctl restart docker

docker pull registry.ivixq.com:4000/registry
Using default tag: latest
Trying to pull repository registry.ivixq.com:4000/registry ... 
latest: Pulling from registry.ivixq.com:4000/registry
12a7970a6783: Pull complete 
bb9291d659e1: Pull complete 
c71426f9b69b: Pull complete 
2e70e7c5f4fd: Pull complete 
267774bac577: Pull complete 
Digest: sha256:437df2cf9a6553a91552f716e7b51f696e98aae6e961bf74e113b0363e913480

# 查看images,发现image已经下载到本地

docker images
REPOSITORY                         TAG                 IMAGE ID            CREATED             SIZE
registry.ivixq.com:4000/registry   latest              047218491f8c        9 days ago          33.17 MB

这样一个本地的registry服务就可以正常使用了,但是如此任何人都可以任意访问私有仓库的images,这样不安全,我想只有授权的用户才能访问pull和push。
我这里使用nginx反向代理client的请求,并用nginx的basic认证来限定用户的访问

删除刚才启动的registry

docker ps
CONTAINER ID        IMAGE                       COMMAND                  CREATED             STATUS              PORTS                    NAMES
84995f349ade        docker.io/registry:latest   "/entrypoint.sh /etc/"   17 hours ago        Up 15 hours         0.0.0.0:4000->5000/tcp   registry

docker rm -f registry

docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

创建启动新容器

docker run -d -p 4000:5000 --restart=always --name registry \
  -v /mydata/registry/conf/config.yml:/etc/docker/registry/config.yml \
  -v /mydata/registry/data:/var/lib/registry \
  docker.io/registry:latest

打tag,push

docker tag c981855ea126 127.0.0.1:4000/centos:lasest

docker tag push 127.0.0.1:4000/centos:lasest
Error response from daemon: no such id: push
[root@cinder ~]# docker push 127.0.0.1:4000/centos:lasest
The push refers to a repository [127.0.0.1:4000/centos]
34e7b85d83e4: Pushed 
lasest: digest: sha256:c5c9a0dd49f7a06ba7c298c498f310924d567b33c8e9bcb97c32ab89a448b3e6 size: 529

可以看出我们这次push的地址127.0.0.1,成功push,如果换成10.1.1.40呢?

docker tag c981855ea126 10.1.1.40:4000/centos:lasest
[root@cinder ~]# docker push 10.1.1.40:4000/centos:lasest
The push refers to a repository [10.1.1.40:4000/centos]
Get https://10.1.1.40:4000/v1/_ping: http: server gave HTTP response to HTTPS client

可以看出使用10.1.1.40地址会报错,和最开始时的报错信息相同,也就是说如果没有证书,是无法从远程主机push和pull的,但是使用127.0.0.1的地址就可以,

# 安装nginx

yum install niginx

# 重新生成自签证书

mkdir -pv /etc/nginx/ssl

cd /etc/nginx/ssl

openssl req -newkey rsa:4096 -nodes -sha256 -keyout iflys.cn.key -x509 -days 365 -out iflys.cn.crt
Generating a 4096 bit RSA private key
.........................................++
..................................................................++
writing new private key to 'iflys.cn.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) []:GD
Locality Name (eg, city) [Default City]:GZ
Organization Name (eg, company) [Default Company Ltd]:GZ
Organizational Unit Name (eg, section) []:GZ
Common Name (eg, your name or your server's hostname) []:www.iflys.cn    
Email Address []:admin@iflys.cn

# 在nginx.conf中配置全局参数

vim nginx.conf
user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    include /etc/nginx/conf.d/*.conf;
}

# 配置虚拟主机

vim /etc/nginx/conf.d/registry.conf
upstream registry {
        server 127.0.0.1:4000;
}

server {
        listen 443;
        server_name www.iflys.cn;

        ssl on;
        ssl_certificate /etc/nginx/ssl/iflys.cn.crt;
        ssl_certificate_key /etc/nginx/ssl/iflys.cn.key;

        # Recommendations from https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html
        ssl_session_cache shared:SSL:1m;
        ssl_session_timeout 5m;

        ssl_prefer_server_ciphers on;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_dhparam /etc/nginx/ssl/dhparam.pem;

        ssl_ciphers 'EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5';

       #ssl_stapling on;
       #ssl_stapling_verify on;

        # disable any limits to avoid HTTP 413 for large image uploads
        client_max_body_size 0;

        # Recommendations from https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html
        chunked_transfer_encoding on; # required to avoid HTTP 411


        location /v2/ {
                if ($http_user_agent ~ "^(docker\/1\.(3|4|5(?!\.[0-9]-dev))|Go ).*$" ) {
                    return 404;
                }
         add_header 'Docker-Distribution-Api-Version' 'registry/2.0' always;

         proxy_pass http://registry;
         proxy_set_header Host $http_host;   # required for docker client‘s sake
         proxy_set_header X-Real-IP $remote_addr; # pass on real client‘s IP
         proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
         proxy_set_header X-Forwarded-Proto $scheme;
         proxy_read_timeout 900;

         auth_basic "Registry realm";
         auth_basic_user_file /etc/nginx/conf.d/.htpasswd;
        }
    }

# 生成dhparam.pem文件

openssl dhparam -out /etc/nginx/ssl/dhparam.pem 2048

# 生成密码文件

yum install httpd-tools
htpasswd -cb /etc/nginx/conf.d/.htpasswd admin admin

# 重启nginx服务

nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

nginx -s reload

# 添加域名解析

vim /etc/hosts
10.1.1.40   www.iflys.cn

验证服务

# 登录成功

curl -i -k https://admin:admin@www.iflys.cn/v2/
HTTP/1.1 200 OK
Server: nginx/1.10.3
Date: Tue, 14 Mar 2017 09:28:14 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 2
Connection: keep-alive
Docker-Distribution-Api-Version: registry/2.0
X-Content-Type-Options: nosniff
Docker-Distribution-Api-Version: registry/2.0

HTTP/1.1 200 OK验证成功

# 直接tag,push

docker tag c981855ea126 www.iflys.cn/centos:latest
docker push www.iflys.cn/centos:latest
The push refers to a repository [www.iflys.cn/centos]
Get https://www.iflys.cn/v1/_ping: x509: certificate signed by unknown authority

有报错信息,也是因为无法验证registry发来的证书,我们需要给docker daemon设置一个证书
# 拷贝证书

mkdir /etc/docker/certs.d/www.iflys.cn
cp /etc/nginx/ssl/iflys.cn.crt /etc/docker/certs.d/www.iflys.cn/

# 重启服务

systemctl restart docker

直接push

docker push www.iflys.cn/centos:latest

docker push www.iflys.cn/centos:latest
The push refers to a repository [www.iflys.cn/centos]

no basic auth credentials

提示没有认证的凭据

我们登录一下

docker login https://www.iflys.cn/v2/
Username: admin
Password: 
Login Succeeded

再push

docker push www.iflys.cn/centos:latest
The push refers to a repository [www.iflys.cn/centos]
0912b310db10: Pushed 
6767cac03a2d: Pushed 
f38182d44088: Layer already exists 
b5aac7bb5fdf: Pushed 
9f8566ee5135: Pushed 
latest: digest: sha256:437df2cf9a6553a91552f716e7b51f696e98aae6e961bf74e113b0363e913480 size: 1364

哈,终于push成功了。
那么用户的认证信息保存在什么位置呢?当登录成功后,会在用户的家目录下面建立一个.docker文件夹并在该文件夹下有一个config.json,在这个文件内保存用户的凭据

cat .docker
.docker/     .docker.bak/ 
[root@cinder ~]# cat .docker/config.json 
{
	"auths": {
		"https://www.iflys.cn/v2/": {
			"auth": "YWRtaW46YWRtaW4="
		}
	}
}

重新创建一个用户

htpasswd -m /etc/nginx/conf.d/.htpasswd yxq
New password: 
Re-type new password: 
Adding password for user yxq

查看用户的密码

cat /etc/nginx/conf.d/.htpasswd 
admin:$apr1$9i03xbwl$FPxFrmTX3d.93lvPVqZbx0
yxq:$apr1$Dw1tr.qw$KvONLqO.S5Zpa6Rm5O6Xk0

重新登录

docker login https://www.iflys.cn/v2/
Username (admin): yxq
Password: 
Login Succeeded

再tag,push一个image

docker tag 6b914bbcb89e www.iflys.cn/nginx:latest
docker pull www.iflys.cn/nginx:latest
Trying to pull repository www.iflys.cn/nginx ... 
latest: Pulling from www.iflys.cn/nginx
Digest: sha256:7f9c22c6b2ba14c609588a794fb40366c5d1eea2c70b8bb7474583994dab9e70

再查看用户的凭据

cat .docker/config.json 
{
	"auths": {
		"https://www.iflys.cn/v2/": {
			"auth": "eXhxOnRvbnk="
		}
	}
}

最后,如果其他docker主机需要使用registry,必须将ca证书放置在/etc/dokcer/certs.d/yourdomain/目录下,然后重新启动docker。

至此registry就安装完毕。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值