Docker Registry作为Docker的核心组件之一负责镜像内容的存储与分发。客户端的docker pull以及push命令都将直接与registry进行交互,最初版本的registry 由Python实现,由于设计初期在安全性,性能以及API的设计上有着诸多的缺陷,该版本在0.9之后停止了开发,由新的项目distribution(新的docker register被称为Distribution)来重新设计并开发下一代registry。
新的项目由go语言开发,所有的API,底层存储方式,系统架构都进行了全面的重新设计已解决上一代registry中存在的问题,2016年4月份rgistry 2.0正式发布,docker 1.6版本开始支持registry 2.0,而八月份随着docker 1.8 发布,docker hub正式启用2.1版本registry全面替代之前版本registry,新版registry对镜像存储格式进行了重新设计并和旧版不兼容,docker 1.5和之前的版本无法读取2.0的镜像。
另外,Registry2.4版本之后支持了回收站机制,也就是可以删除镜像了,在2.4版本之前是无法支持删除镜像的,所以如果你要使用最好是大于Registry2.4版本的,目前最新版本为2.7.x。
官方文档地址:https://docs.docker.com/registry/
官方github地址:https://github.com/docker/distribution

搭建单机版仓库(https)

创建凭据存储目录

[root@mysql ~]# mkdir auth certs
## 创建生成证书索引数据库文件
[root@mysql ~]# touch /etc/pki/CA/index.txt

## 指定第一个颁发证书的序列号
[root@mysql ~]# echo 01 > /etc/pki/CA/serial

## 生成私钥

# (umask 066; openssl genrsa -out /etc/pki/tls/private/dker-registry.key 4096)

## 申请证书文件
# openssl req -new -key /etc/pki/tls/private/dker-registry.key -days 365 -out /etc/pki/tls/dker-registry.csr

## 签署证书
# openssl ca -in /etc/pki/tls/dker-registry.csr -out /etc/pki/CA/certs/docker-reg.crt -days 365

注意:默认国家,省,公司名称三项必须和CA一致,Common Name就是证书签发的地址(即:仓库地址,如果是域名,需要添加DNS解析的)
# mv /etc/pki/CA/certs/docker-reg.crt certs/

# mv /etc/pki/tls/private/dker-registry.key ~/certs/

创建用户和凭据

[root@mysql ~]# docker run   --entrypoint htpasswd   httpd:2 -Bbn testuser testpassword > auth/htpasswd

启动registery

查看证书目录

[root@mysql ~]# ll auth/ certs/
auth/:
total 4
-rw------- 1 root root 67 Jul  5 14:06 htpasswd

certs/:
total 12
-rw------- 1 root root 3243 Jul  7 21:28 dker-registry.key
-rw-r--r-- 1 root root 7294 Jul  7 21:36 docker-reg.crt

启动容器

[root@mysql ~]# docker run -d \
> -p 5000:5000 \
> --restart=always \
> --name registry \
> -v "$(pwd)"/auth:/auth \
> -e "REGISTRY_AUTH=htpasswd" \
> -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
> -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
> -v "$(pwd)"/certs:/certs \
> -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/docker-reg.crt \
> -e REGISTRY_HTTP_TLS_KEY=/certs/dker-registry.key \
> registry:2

查看启动的容器

[root@mysql ~]# docker ps
CONTAINER ID   IMAGE        COMMAND                  CREATED         STATUS         PORTS                                       NAMES
d75e6dc66de4   registry:2   "/entrypoint.sh /etc…"   5 minutes ago   Up 5 minutes   0.0.0.0:5000->5000/tcp, :::5000->5000/tcp   registry


[root@mysql ~]# ss -lntp
State       Recv-Q Send-Q                   Local Address:Port                                  Peer Address:Port              
LISTEN      0      128                                  *:22                                               *:*                   users:(("sshd",pid=858,fd=3))
LISTEN      0      100                          127.0.0.1:25                                               *:*                   users:(("master",pid=1010,fd=13))
LISTEN      0      4096                                 *:5000                                             *:*                   users:(("docker-proxy",pid=2192,fd=4))
LISTEN      0      128                                 :::22                                              :::*                   users:(("sshd",pid=858,fd=4))
LISTEN      0      100                                ::1:25                                              :::*                   users:(("master",pid=1010,fd=14))
LISTEN      0      4096                                :::5000                                            :::*                   users:(("docker-proxy",pid=2196,fd=4))

添加信任仓库

[root@mysql ~]# vim /lib/systemd/system/docker.service 
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service containerd.service
Wants=network-online.target
Requires=docker.socket containerd.service

[Service]
Type=notify
# the default is not to use systemd for cgroups because the delegate issues still
# exists and systemd currently does not support the cgroup feature set required
# for containers run by docker
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --insecure-registry=zhanghao:443

或者在/etc/docker/daemon.json文件中添加

[root@apache ~]# cat /etc/docker/daemon.json 
{
  "registry-mirrors": ["https://05eotbde.mirror.aliyuncs.com"],
   "insecure-registries": ["zhanghao:443"]
}

重启docker

[root@mysql ~]# systemctl daemon-reload 
[root@mysql ~]# systemctl restart docker

上传镜像到镜像仓库

# 从官方镜像仓库拉取镜像
[root@mysql ~]# docker pull ubuntu:16.04

# 给镜像打标
[root@mysql ~]# docker tag ubuntu:16.04 zhanghao:443/my-ubuntu

# 登录仓库
[root@mysql ~]# docker login -u test zhanghao:443
Password: 
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

# 上传镜像到镜像仓库
[root@mysql ~]# docker push zhanghao:443/my-ubuntu
Using default tag: latest

注意:镜像仓库登录的时候,加密的密码信息写在了如下文件

[root@docker01 src]# cat /root/.docker/config.json
{
    "auths": {
        "mytest.harbor.com": {
            "auth": "YWRtaW46SGFyYm9yMTIzNDU="
        },
        "mytest.harbor.com:80": {
            "auth": "YWRtaW46SGFyYm9yMTIzNDU="
        }
    },
    "HttpHeaders": {
        "User-Agent": "Docker-Client/18.09.9 (linux)"
    }

另一台服务器拉取镜像仓库中的镜像

[root@apache ~]# docker pull zhanghao:443/my-ubuntu
Using default tag: latest
latest: Pulling from my-ubuntu
61e03ba1d414: Pull complete 
4afb39f216bd: Pull complete 
e489abdc9f90: Pull complete 
999fff7bcc24: Pull complete 
Digest: sha256:114bbce1997fa476da56c3958cb3ca13269a54b0a97dfd3667543c7778287bf2
Status: Downloaded newer image for zhanghao:443/my-ubuntu:latest

在客户端查看仓库中的所有镜像

[root@apache ~]# curl -u test -k https://zhanghao:443/v2/_catalog
Enter host password for user 'test':
{"repositories":["my-ubuntu"]}

网页中访问

docker registry 注册 docker registery_mysql

注意

[root@docker01 src]# vim /etc/docker/daemon.json 
{
  "registry-mirrors": ["https://05eotbde.mirror.aliyuncs.com"],
   "insecure-registries": ["zhanghao:443","mytest.harbor.com"]
}

如果镜像仓库配置的时候写了端口,那么登录和打标记的时候也要加上端口,否则找不到仓库和镜像

[root@docker01 src]# systemctl restart docker
[root@docker01 src]# docker login -u admin http://mytest.harbor.com
Password: 
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

登录加端口的情况

[root@docker01 src]# docker login -u admin http://mytest.harbor.com:80
Password: 
Error response from daemon: Get https://mytest.harbor.com:80/v2/: http: server gave HTTP response to HTTPS client

测试打标和推送镜像

[root@docker01 src]# docker tag nginx:1.16.1-alpine mytest.harbor.com/test/nginx:1.16.1-alpine


[root@docker01 src]# docker push mytest.harbor.com/test/nginx:1.16.1-alpine
The push refers to repository [mytest.harbor.com/test/nginx]
08065237b498: Layer already exists 
531743b7098c: Layer already exists 
1.16.1-alpine: digest: sha256:0dfc8450deb8c7f06fbaac27e453ac3262df7d3a93639c4e2f48ee39434ec017 size: 739

加端口的情况

[root@docker01 src]# docker push mytest.harbor.com:80/test/nginx:test
The push refers to repository [mytest.harbor.com:80/test/nginx]
Get https://mytest.harbor.com:80/v2/: http: server gave HTTP response to HTTPS client