在开始之前,需要问一个问题:docker的私有仓库,nexus3和harbor哪个好用?

我的回答是,没有好与不好之分,只有适合与不适合。就像张戈大佬在回答提问时说的:harbor应该更专业,但是更重,要部署N个组件(虽然也可以用docker部署)。nexus3覆盖更全面,啥都可以做,是一个混合仓库,一个能抵多个,主要还是看场景。

因为我之前用nexus3做了maven、yum、npm的私服,所以对我来说,用nexus3是最为方便和快捷的。

一、安装nexus3

安装之前已经讲过了,有需要可以移步至nexus3的安装

二、配置nexus

1、创建Blob Stores

和之前maven、npm、yum一样,这里新建一个blob store专门作为docker的存储。

1)Type
选择"File"。

2)Name
就叫docker-blob吧。

3)Enable Soft Quota
限制目录的大小。我这边就不限制了。如果要限制的话,就勾选上,并填上限制的条件和限制的值就OK了。

4)Path

在填入Name之后,path会自动生成。

nexus搭建docker nexus docker_redis

2、创建 一个hosted类型的仓库

用户可以把一些镜像push到宿主仓库(Hosted Repository)中。

点击"Repository"–>“Repositories”–>“Create repository”,选择docker(hosted)。

nexus搭建docker nexus docker_nexus_02

1)Name
就叫docker-hosted-my吧。

2)Online
勾选,可以设置这个仓库是在线还是离线。

3)Repository Connectors
包含HTTP和HTTPS两种port。下面的说明中讲的很清楚:是允许客户端直接连接到hosted仓库用的,并根据自己的需求选择是用http还是https。

我这里选择http,端口设置为9083,用于后面的nginx代理的后端。

4)Allow anonymous docker pull
不勾选,这样即使是docker pull操作,也需要先用docker login登录之后才能拉取镜像。

5)Docker Registry API Support
Docker registry默认是使用API v2,为了兼容性,可以勾选启用API v1。

6)Storang
Blob store:选择此仓库使用的Blob存储,这里选择之前创建的docker-blob。
Strict Content Type Validation:验证上传内容格式,这里就用默认的勾选。

7)Hosted
Deployment Policy:部署策略,有三个选项,分别是:
Allow Redeploy:允许重新部署
Disable Redeploy:禁止重新部署
Read-Only:只读

我这里使用默认的"Allow redeploy",如果是生产环境,可以选择"Allow redeploy"。

8)Cleanup
Cleanup Policies:清除策略,这个是新增的功能,这里先不进行设置。

配置完成后如下图

nexus搭建docker nexus docker_nexus搭建docker_03

3、创建一个proxy类型的仓库

代理仓库(Proxy Repository)是远程仓库的代理,当用户向这个代理仓库请求一个依赖包时,这个代理仓库会先在本地查找,如果存在,会直接提供给用户进行下载;如果在代理仓库本地查找不到,就会从配置的远程中央仓库中进行下载,下载到私服上之后再提供给用户下载。所以一般我们把私服架设在内网之中,这样可以节省外网带宽,并且大大提高了用户下载依赖的速度。

点击"Repository"–>“Repositories”–>“Create repository”,选择docker(proxy)。

1)Name
因为我要代理daocloud的docker镜像加速地址,所以就叫"docker-proxy-daocloud"。

2)Online
勾选,设置成在线。

3)Allow anonymous docker pull
不勾选,这样即使是docker pull操作,也需要先用docker login登录之后才能拉取镜像。

4)Docker Registry API Support
Docker registry默认是使用API v2,为了兼容性,可以勾选启用API v1。

5)Proxy
Remote storage:设置远程仓库的地址,我这里设置成daocloud的docker镜像加速地址—http://f1361db2.m.daocloud.io

这里为了确保能够拉取DockerHub最新的镜像,我选择了Use DockerHub这个Index。

其他使用默认配置。

6)Storage
Blob store:选择docker-blob
Strict Content Type Validation:验证上传内容格式,这里就用默认的勾选。

7)Routing Rule,Negative Cache,Cleanup,HTTP
都使用默认配置。

配置完成后如下图

nexus搭建docker nexus docker_redis_04

4、创建一个group类型的仓库

仓库组(Repository Group)的目的是将多个仓库(代理仓库和宿主仓库)聚合,对用户暴露统一的地址。当用户需要获取某一个镜像时,请求的是仓库组的地址,系统将会根据仓库组配置的仓库顺序依次查找。

点击"Repository"–>“Repositories”–>“Create repository”,选择docker(gruop)。

1)Name
docker-group-my

2)Online
勾选,设置成在线

3)Repository Connectors
启用http连接器,端口设置为9082

4)Allow anonymous docker pull
不勾选,这样即使是docker pull操作,也需要先用docker login登录之后才能拉取镜像。

5)Docker Registry API Support
Docker registry默认是使用API v2,为了兼容性,可以勾选启用API v1。

6)Storage
Blob store:选择docker-blob
Strict Content Type Validation:使用默认的勾选

7)Group

将左侧的Available中的仓库列表添加到右侧的Members中。

nexus搭建docker nexus docker_nginx_05

OK,到这里,nexus3上docker仓库的配置基本完成了。但是这样并不能很好的使用。因为group仓库并不能推送镜像,推送自己制作的镜像到仓库还得通过本地仓库(hosted类型的仓库)的端口去推送,很不方便。

下面是参考张戈博客的一个通过nginx来判断镜是推镜像还是拉镜像,然后代理到不同的端口,也是非常感谢张戈大佬。

三、配置nginx

在nexus服务器上安装好nginx之后,我们需要生成自签名SSL证书,因为后面不想在docker pull的时候还要带上一个端口!这里就用docker.mynexus.com作为docker仓库的域名。

生成自签名证书的方法网上有很多,这里推荐一个一键生成的工具,地址为https://github.com/Fishdrowned/ssl,使用的方法作者已经写的很详细了。生成方式如下:

[root@nexus3 ~]# cd /usr/local/nginx/conf/

# 克隆工具
[root@nexus3 conf]# git clone https://github.com/Fishdrowned/ssl.git
Cloning into 'ssl'...
remote: Enumerating objects: 112, done.
remote: Total 112 (delta 0), reused 0 (delta 0), pack-reused 112
Receiving objects: 100% (112/112), 173.19 KiB | 254.00 KiB/s, done.
Resolving deltas: 100% (51/51), done.

# 生成证书
[root@nexus3 conf]# cd ssl/
[root@nexus3 ssl]# ls
ca.cnf  docs  flush.sh  gen.cert.sh  gen.root.sh  LICENSE  README.md
[root@nexus3 ssl]# ./gen.cert.sh docker.mynexus.com
Removing dir out
Creating output structure
Done
Generating a 2048 bit RSA private key
.......+++
......+++
writing new private key to 'out/root.key.pem'
-----
Generating RSA private key, 2048 bit long modulus
........+++
.....................+++
e is 65537 (0x10001)
Using configuration from ./ca.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName           :PRINTABLE:'CN'
stateOrProvinceName   :ASN.1 12:'Guangdong'
localityName          :ASN.1 12:'Guangzhou'
organizationName      :ASN.1 12:'Fishdrowned'
organizationalUnitName:ASN.1 12:'docker.mynexus.com'
commonName            :ASN.1 12:'*.docker.mynexus.com'
Certificate is to be certified until Dec 25 10:52:19 2021 GMT (730 days)

Write out database with 1 new entries
Data Base Updated

Certificates are located in:
lrwxrwxrwx 1 root root 45 Dec 26 18:52 /usr/local/nginx/conf/ssl/out/docker.mynexus.com/docker.mynexus.com.bundle.crt -> ./20191226-1852/docker.mynexus.com.bundle.crt
lrwxrwxrwx 1 root root 38 Dec 26 18:52 /usr/local/nginx/conf/ssl/out/docker.mynexus.com/docker.mynexus.com.crt -> ./20191226-1852/docker.mynexus.com.crt
lrwxrwxrwx 1 root root 15 Dec 26 18:52 /usr/local/nginx/conf/ssl/out/docker.mynexus.com/docker.mynexus.com.key.pem -> ../cert.key.pem
lrwxrwxrwx 1 root root 11 Dec 26 18:52 /usr/local/nginx/conf/ssl/out/docker.mynexus.com/root.crt -> ../root.crt

在nginx中增加如下配置:

upstream nexus_docker_get {
    server 192.168.0.125:9082;
}
 
upstream nexus_docker_put {
    server 192.168.0.125:9083;
}

server {
    listen 80;
    listen 443 ssl;
    server_name docker.mynexus.com;
    access_log logs/docker.mynexus.com access_json;
    # 证书
    ssl_certificate /usr/local/nginx/conf/ssl/out/docker.mynexus.com/docker.mynexus.com.crt;
    ssl_certificate_key /usr/local/nginx/conf/ssl/out/docker.mynexus.com/docker.mynexus.com.key.pem;
    ssl_protocols TLSv1.1 TLSv1.2;
    ssl_ciphers '!aNULL:kECDH+AESGCM:ECDH+AESGCM:RSA+AESGCM:kECDH+AES:ECDH+AES:RSA+AES:';
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    # disable any limits to avoid HTTP 413 for large image uploads
    client_max_body_size 0;
    # required to avoid HTTP 411: see Issue #1486 (https://github.com/docker/docker/issues/1486)
    chunked_transfer_encoding on;
    # 设置默认使用推送代理
    set $upstream "nexus_docker_put";
    # 当请求是GET,也就是拉取镜像的时候,这里改为拉取代理,如此便解决了拉取和推送的端口统一
    if ( $request_method ~* 'GET') {
        set $upstream "nexus_docker_get";
    }
    # 只有本地仓库才支持搜索,所以将搜索请求转发到本地仓库,否则出现500报错
    if ($request_uri ~ '/search') {
        set $upstream "nexus_docker_put"; 
    }  
    index index.html index.htm index.php;
    location / {
            proxy_pass http://$upstream;
            proxy_set_header Host $host;
            proxy_connect_timeout 3600;
            proxy_send_timeout 3600;
            proxy_read_timeout 3600;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_buffering off;
            proxy_request_buffering off;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto http;
    }
}

加完配置之后,reload一下

[root@localhost conf]# /usr/local/nginx/sbin/nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
[root@localhost conf]# /usr/local/nginx/sbin/nginx -s reload

四、配置docker客户端

nginx部署完成之后,找一台客户机进行测试,先在客户机的hosts文件中加入刚才定义的内部使用的域名解析。然后还需要在客户端将自签名的根证书(ca.crt)导入到客户端才能正常使用,否则会报不信任错误。

在上文介绍的一键生成自签名证书工具中,会生成一个根证书,名称为/usr/local/nginx/conf/ssl/out/docker.mynexus.com/root.crt,将这个文件上传到客户端服务器的/etc/docker/certs.d/docker.mynexus.com目录即可(注意目录需要创建,最后的文件夹和仓库域名保持一致:docker.mynexus.com)。

找一台测试机:

[root@localhost ~]# echo '192.168.0.125 docker.mynexus.com' >> /etc/hosts
[root@localhost ~]# mkdir -p /etc/docker/certs.d/docker.mynexus.com

再把nexus服务器上的根证书拷贝到客户机上

[root@nexus3 ~]# scp /usr/local/nginx/conf/ssl/out/docker.mynexus.com/root.crt 192.168.0.151:/etc/docker/certs.d/docker.mynexus.com/

然后就可以开始使用了。

五、测试验证

1、pull一个镜像
[root@localhost ~]# docker pull docker.io/redis
Using default tag: latest
latest: Pulling from library/redis
000eee12ec04: Pull complete 
5cc53381c195: Pull complete 
48bb7bcb5fbf: Pull complete 
ef8a890bb1c2: Pull complete 
32ada9c6fb0d: Pull complete 
76e034b0f296: Pull complete 
Digest: sha256:1eedfc017b0cd3e232878ce38bd9328518219802a8ef37fe34f58dcf591688ef
Status: Downloaded newer image for redis:latest
docker.io/library/redis:latest
[root@localhost ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
redis               latest              dcf9ec9265e0        4 weeks ago         98.2MB
2、登录docker私服
[root@localhost ~]# docker login -u admin -p Abc@123456 docker.mynexus.com
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
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
3、打标签

这里的版本号是我随便取的!!!

[root@localhost ~]# docker tag redis docker.mynexus.com/redis:v111
[root@localhost ~]# docker images
REPOSITORY                 TAG                 IMAGE ID            CREATED             SIZE
redis                      latest              dcf9ec9265e0        4 weeks ago         98.2MB
docker.mynexus.com/redis   v111                dcf9ec9265e0        4 weeks ago         98.2MB
4、push镜像到私服
[root@localhost ~]# docker push docker.mynexus.com/redis:v111
The push refers to repository [docker.mynexus.com/redis]
24597674dcad: Pushed 
85835f84dadf: Pushed 
14d62da63315: Pushed 
1771f54cbd23: Pushed 
600b5cf9c806: Pushed 
831c5620387f: Pushed 
v111: digest: sha256:e73ef998c22f9a98793d9951bb2915cd945d8fa6f9ec1b324e85d19617efc2fd size: 1572

然后看一眼私服

nexus搭建docker nexus docker_nexus搭建docker_06

redis镜像被成功的push到私服上了。

5、从私服拉镜像

1)pull一个私服存在的镜像

就是刚才我push上去的redis镜像。

[root@localhost ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
[root@localhost ~]# docker pull docker.mynexus.com/redis:v111
v111: Pulling from redis
000eee12ec04: Pull complete 
5cc53381c195: Pull complete 
48bb7bcb5fbf: Pull complete 
ef8a890bb1c2: Pull complete 
32ada9c6fb0d: Pull complete 
76e034b0f296: Pull complete 
Digest: sha256:e73ef998c22f9a98793d9951bb2915cd945d8fa6f9ec1b324e85d19617efc2fd
Status: Downloaded newer image for docker.mynexus.com/redis:v111
docker.mynexus.com/redis:v111
[root@localhost ~]# docker images
REPOSITORY                 TAG                 IMAGE ID            CREATED             SIZE
docker.mynexus.com/redis   v111                dcf9ec9265e0        4 weeks ago         98.2MB

2)pull一个私服上不存在的镜像

比如拉取一个centos镜像,这个在现在的私服上是不存在的

[root@localhost ~]# docker pull docker.mynexus.com/centos
Using default tag: latest
latest: Pulling from centos
729ec3a6ada3: Pull complete 
Digest: sha256:6ab380c5a5acf71c1b6660d645d2cd79cc8ce91b38e0352cbf9561e050427baf
Status: Downloaded newer image for docker.mynexus.com/centos:latest
docker.mynexus.com/centos:latest

可以看到已经成功将centos镜像pull下来了,再看一眼私服。

nexus搭建docker nexus docker_redis_07

私服中之前虽然没有centos这个镜像,但是它从代理的远程仓库中下载了这个镜像并存在了私服中。等下次再拉取这个镜像的时候,就可以直接从私服中拉取。这个和之前作为maven、npm、yum私服的原理是一样的。

参考文章:
http://www.eryajf.net/1816.htmlhttps://zhang.ge/5139.html