> For the complete documentation index, see [llms.txt](https://darren.gitbook.io/project/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://darren.gitbook.io/project/devops/kai-yuan-cang-ku-nexus/er-shi-yong-nexus3-pei-zhi-docker-si-you-cang-ku.md).

# 二，使用nexus3配置docker私有仓库

公司已经有harbor作为docker的镜像仓库，但Harbor只能作为私有仓库，当需要Docker Hub或其他远程仓库上的镜像时，他就无能为力了。我们就只能手动到远程仓库上进行下载，再重新打标签，然后在推到harbor上，才能使用。

我们想要的仓库应该是既能充当私有仓库，又能在你拉取本地没有的镜像时，同步远程的公共镜像仓库，说了这些，就想起，java项目的日常依赖解决，大概也是这么一个思路。

而为java项目提供私有仓库服务的nexus3，正好也支持docker仓库，不仅如此，他还支持yum, apt, npm, ruby gems, pypi 等诸多类型的仓库功能。因此，我们大概可以感受到，`学会nexus3，走遍天下都不怕！`

那么今天，就先来讲解研究一下，如何使用nexus3来配置成docker的私有仓库。

### 1，安装nexus3。

这个地方略了，安装部署可以参考：[nexus3安装配置。](http://www.eryajf.net/1803.html)

### 2，配置走起。

#### 1，创建blob存储。

登陆之后，先创建一个用于存储镜像的空间。

![](http://www.eryajf.net/wp-content/uploads/2018/10/2018101611425155.jpg)

定义一个name，下边的内容会自动补全。

![](http://www.eryajf.net/wp-content/uploads/2018/10/2018101611425286.jpg)

然后保存。

![](http://www.eryajf.net/wp-content/uploads/2018/10/2018101611425392.jpg)

这里因为我用的测试服务器演示，因此存储没有那么大，实际生产中使用，建议服务器存储500G或以上。

#### 2，创建一个hosted类型的docker仓库。

Hosted类型仓库用作我们的私有仓库，替代harbor的功能。

点击步骤如下：

![](http://www.eryajf.net/wp-content/uploads/2018/10/2018101611425410.jpg)

而后可见：

![](http://www.eryajf.net/wp-content/uploads/2018/10/2018101611425659.jpg)

所支持种类之丰富，可见一斑。

这里我们看到docker类型有三种：

* `hosted` : 本地存储，即同 docker 官方仓库一样提供本地私服功能。<br>
* `proxy` : 提供代理其他仓库的类型，如 docker 中央仓库。<br>
* `group` : 组类型，实质作用是组合多个仓库为一个地址。

我们先来创建一个hosted类型的私有仓库。

点击 `Repository`下面的 `Repositories` – Create repository – `docker(hosted)` :

`Name`: 定义一个名称docker-local

`Online`: 勾选。这个开关可以设置这个Docker repo是在线还是离线。

`Repository Connectors`

* 下面包含HTTP和HTTPS两种类型的port。
* <br>
* 有什么用呢？说明讲得很清楚：

我们把HTTP这里勾选上，然后设置端口为8083。

`Force basic authentication`

* 勾选
* 。这样的话就不允许匿名访问了，执行docker pull或 docker push之前，都要先登录：docker login

`Docker Registry API Support`

* Docker registry默认使用的是API v2, 但是为了兼容性，我们可以
* 勾选启用API v1
* 。

`Storage`

`Blob store`：我们下拉选择前面创建好的专用blob：idocker-hub。

`Hosted`

* 开发环境，我们运行重复发布，因此Delpoyment policy 我们选择
* Allow redeploy
* 。

整体配置截图如下：

![](http://www.eryajf.net/wp-content/uploads/2018/10/2018101611425629.jpg)

#### 3，创建一个proxy类型的docker仓库。

proxy类型仓库，可以帮助我们访问不能直接到达的网络，如另一个私有仓库，或者国外的公共仓库，如官方的dockerhub镜像库。

创建一个proxy类型的仓库

```
创建一个proxy类型的仓库

Name: proxy-docker-hub
Repository Connectors: 不设置。
Proxy
Remote Storage: docker hub的proxy，这里填写: https://registry-1.docker.io
这个是官方默认的一个链接，我这里配置使用DaoCloud的容器加速：http://f1361db2.m.daocloud.io
Docker Index： Use Docker Hub
Storage：idocker-hub
```

整体配置截图如下：

![](http://www.eryajf.net/wp-content/uploads/2018/10/2018101611425883.jpg)

#### 4，创建一个group类型的docker仓库。

group类型的docker仓库，是一个聚合类型的仓库。它可以将前面我们创建的3个仓库聚合成一个URL对外提供服务，可以屏蔽后端的差异性，实现类似透明代理的功能。

`name`：docker-group

`Repository Connectors`：启用了一个监听在8082端口的http连接器；

`Storage`：选择专用的blob存储idocker-hub。

`group` : 将左边可选的3个仓库，添加到右边的members下。

整体配置截图如下：

![](http://www.eryajf.net/wp-content/uploads/2018/10/2018101611430335.jpg)

到这儿，nexus3的配置算是完成了，接下来就是使用方面的事情了。

### 4，常规方式使用。

请注意，这种方式经我测试，总是失败，原因还没查出来。如果有人知道原因是什么，麻烦留言区告知一下。

#### 1，配置

配置`/etc/docker/daemon.json`， 由于不是https，所以要在daemon.json中配置一下：

```
{ "insecure-registries":["192.168.157.110:8082"] }
```

#### 2，重启docker。

```
$systemctl daemon-reload
$systemctl restart docker
```

#### 3，pull镜像。

```
docker pull redis
```

#### 4，登陆私服。

```
docker login -u admin -p admin123 192.168.157.110:8082
```

#### 5，打标签。

```
docker tag docker.io/redis 192.168.157.110:8082/redis
```

#### 6，push镜像。

```
[root@docker ~]$docker push 192.168.157.110:8082/redis 然后报错： The push refers to a repository [192.168.157.110:8082/redis]902afb26cfff: Layer already exists21497520b817: Layer already existsa3514b4102be: Layer already exists714e32c05337: Layer already existsd98fb630fb3b: Layer already exists8b15606a9e3e: Layer already existserror parsing HTTP 404 response body: unexpected end of JSON input: ""
```

暂时不知这个报错问题的原因是什么，因为最终没有采用这种方式，所以没有深入探究。

### 5，nginx代理方式。

以下内容参考张戈博客，中有删改。

在部署 Nginx 部分，我们先需要生成自签名 SSL 证书，因为后面不想在 docker pull 的时候还要带一个端口！这里我们需要 2 个域名，一个用来展示 nexus 前台，另一个用做 docker 仓库，比如：

* nexus 前台：`repo.ald.com`<br>
* docker 仓库：`idocker.io`

#### 1，安装nginx。

先通过`curl 192.168.106.10/a | sh`安装nginx。

#### 2，生成证书。

生成自签名 SSL 证书的方法网上很多，这里推荐一个一键生成工具，大家可以尝试使用：\
[ssl](http://www.eryajf.net/go?url=https://github.com/Fishdrowned/ssl)

这个工具。

创建方式如下：

```
#直接切换到应用目录。
[root@nexus ~]$cd /usr/local/nginx/conf 
#下载工具。
[root@nexus conf]$git clone https://github.com/Fishdrowned/ssl.git
Cloning into 'ssl'...remote: Enumerating objects: 106, 
done.remote: Total 106 (delta 0), reused 0 (delta 0), pack-reused 
106Receiving objects: 100% (106/106), 171.53 KiB | 286.00 KiB/s, 
done.Resolving deltas: 100% (48/48), done. 
#生成证书。
[root@nexus ssl]$./gen.cert.sh idocker.ioUsing configuration 
from ./ca.cnfCheck that the request matches the signatureSignature okThe Subject's Distinguished Name is as followscountryName           :PRINTABLE:'CN'stateOrProvinceName   :ASN.1 12:'Guangdong'localityName          :ASN.1 12:'Guangzhou'organizationName      :ASN.1 12:'Fishdrowned'organizationalUnitName:ASN.1 12:'idocker.io'commonName            :ASN.1 12:'*.idocker.io'Certificate is to be certified until Oct 16 06:18:13 2022 GMT (1461 days) Write out database with 1 new entriesData Base Updated Certificates are located in:lrwxrwxrwx 1 root root 37 Oct 16 14:18 /usr/local/nginx/conf/ssl/out/idocker.io/idocker.io.bundle.crt -> ./20181016-1418/idocker.io.bundle.crtlrwxrwxrwx 1 root root 30 Oct 16 14:18 /usr/local/nginx/conf/ssl/out/idocker.io/idocker.io.crt -> ./20181016-1418/idocker.io.crtlrwxrwxrwx 1 root root 15 Oct 16 14:18 /usr/local/nginx/conf/ssl/out/idocker.io/idocker.io.key.pem -> ../cert.key.pemlrwxrwxrwx 1 root root 11 Oct 16 14:18 /usr/local/nginx/conf/ssl/out/idocker.io/root.crt -> ../root.crt
```

#### 3，配置nginx。

将如下配置写入`nginx.conf`。

```
upstream nexus_docker_get {    server 192.168.157.110:8082;} upstream nexus_docker_put {    server 192.168.157.110:8083;}server {    listen 80;    listen 443 ssl;    server_name idocker.io;    access_log /var/log/nginx/idocker.io.log;    # 证书    ssl_certificate /usr/local/nginx/conf/ssl/out/idocker.io/idocker.io.crt;    ssl_certificate_key /usr/local/nginx/conf/ssl/out/cert.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";    }    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;    }}
```

如果有一些操作与本文不一致，那么请根据自己实际情况进行修改。

`nginx -t` 检查没有问题的话，就可以启动nginx了。

#### 4，客户端配置。

部署完成之后，我们就可以找一台测试机器进行测试了，不过因为我们刚刚定义的是内部使用的域名，所以需要在测试机器上写hosts解析，并将证书拷贝过去，否则会报报不信任的错误。

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

现在到一台新主机上测试：

```
[root@docker ~]$echo "192.168.157.110 idocker.io" >> /etc/hosts[root@docker ~]$mkdir -p /etc/docker/certs.d/idocker.io 然后去nexus主机上，将刚才的证书拷过来： scp /usr/local/nginx/conf/ssl/out/root.crt root@192.168.157.106:/etc/docker/certs.d/idocker.io/ca.crt
```

接下来，就可以开始真正的使用了。

### 6，正式验证。

#### 1，pull镜像。

```
[root@docker ~]$docker pull docker.io/nginx
Using default tag: latestTrying to pull repository docker.io/library/nginx 
...latest: Pulling from docker.io/library/nginxf17d81b4b692: 
Pull completed5c237920c39: Pull completea381f92f36de: 
Pull completeDigest: sha256:4ddaf6043a77aa145ce043d4c662e3768556421d6c0a65d303e89977ad3c9636Status: Downloaded newer image for docker.io/nginx:latest 
[root@docker ~]$docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
docker.io/nginx     latest              dbfc48660aeb        45 minutes ago      109 MB
```

#### 2，登陆私服。

这个地方也可能在登陆的时候会报错，说证书过期什么的，如下：

```
[root@moban idocker.io]$docker login -u admin -p admin123 idocker.io
Error response from daemon: Get https://idocker.io/v1/users/: x509: certificate has expired or is not yet valid
```

报这个错的情况下，大概原因只有一个，那就是，两台服务器的时间不一致，只需要将两台服务器时间保持一致即可。

```
yum -y install ntpdate && ntpdate -u cn.pool.ntp.org
```

分别在两台主机执行之后，发现登陆就成功了。

```
[root@docker ~]$docker login -u admin -p admin123 idocker.ioLogin Succeeded
```

#### 3，打标签。

```
[root@docker ~]$docker tag docker.io/nginx idocker.io/nginx [root@docker ~]$docker imagesREPOSITORY          TAG                 IMAGE ID            CREATED             SIZEdocker.io/nginx     latest              dbfc48660aeb        49 minutes ago      109 MBidocker.io/nginx    latest              dbfc48660aeb        49 minutes ago      109 MB
```

#### 4，push镜像。

```
[root@docker ~]$docker push idocker.io/nginxThe push refers to a repository [idocker.io/nginx]86df2a1b653b: Pushedbc5b41ec0cfa: Pushed237472299760: Pushedlatest: digest: sha256:d98b66402922eccdbee49ef093edb2d2c5001637bd291ae0a8cd21bb4c36bebe size: 948
```

这里上传成功了，再去nexus3里边看看是有上去了。

![](http://www.eryajf.net/wp-content/uploads/2018/10/2018101611430374.jpg)

#### 5，测试从私服拉镜像。

```
[root@docker ~]$docker imagesREPOSITORY          TAG                 IMAGE ID            CREATED             SIZE [root@docker ~]$docker pull idocker.io/nginxUsing default tag: latestTrying to pull repository idocker.io/nginx ...latest: Pulling from idocker.io/nginxf17d81b4b692: Pull completed5c237920c39: Pull completea381f92f36de: Pull completeDigest: sha256:d98b66402922eccdbee49ef093edb2d2c5001637bd291ae0a8cd21bb4c36bebeStatus: Downloaded newer image for idocker.io/nginx:latest [root@docker ~]$docker imagesREPOSITORY          TAG                 IMAGE ID            CREATED             SIZEidocker.io/nginx    latest              dbfc48660aeb        59 minutes ago      109 MB
```

### ,7，代理的功能展示。

当某一个镜像在我们本地仓库没有的时候，就需要从远程仓库拉取了，其他的私有仓库的操作大概都是要从远程拉取，然后在重复如上操作推到本地私有仓库，而nexus因为有了proxy功能，因此，当我们在pull远程镜像的时候，本地就会自动同步下来了，这，就是其核心竞争力，也是与其他几款产品本质上的区别。

下边，我以拉取gitlab镜像为例：

```
[root@docker ~]$docker pull idocker.io/gitlab/gitlab-ceUsing default tag: latestTrying to pull repository docker.io/gitlab/gitlab-ce ...latest: Pulling from docker.io/gitlab/gitlab-ce3b37166ec614: Pull complete504facff238f: Pull completeebbcacd28e10: Pull completec7fb3351ecad: Pull complete2e3debadcbf7: Pull complete8e5e9b12009c: Pull complete0720fffe6e22: Pull complete2f336a213238: Pull complete1656ee3e1127: Pull complete25fa5248fd38: Pull complete36b8c1d869a0: Pull completeDigest: sha256:0dd22880358959d9a9233163147adc4c8f1f5d5af90097ff8dfa383c6be7e25aStatus: Downloaded newer image for docker.io/gitlab/gitlab-ce:latest
```

因为本地没有这个镜像，所以从远程仓库拉取，然后去仓库里看看啥情况：

![](http://www.eryajf.net/wp-content/uploads/2018/10/2018120306271494.jpg)

这里可以看到，在我们创建的proxy分组中有一个library目录，已经自动缓存下来了这个镜像。

接着去我们用的group里边看看。

![](http://www.eryajf.net/wp-content/uploads/2018/10/201812030627589.jpg)

我们看到group里边也已经有了gitlab这个镜像，如果以后再有人拉取gitlab这个镜像，直接就可以从本地私服进行拉取了，而不用再到公网去下了，事实上，使用nexus3作为maven的私服其实也是这样一个原理，从而实现节约带宽，节约时间，等等优势。

至此，基本上关于使用nexus3搭建docker私有仓库的知识点，基本上已经知无不言，言无不尽的分享完毕了。

### 8，参考地址。

感恩前行者的付出，让我们能够走得如此顺畅，感谢自己认真钻研，从而能够把好东西用更好的方式分享出去！

[https://zhangge.net/5139.html](http://www.eryajf.net/go?url=https://zhangge.net/5139.html)\
[https://segmentfault.com/a/1190000015629878#articleHeader5](http://www.eryajf.net/go?url=https://segmentfault.com/a/1190000015629878#articleHeader5)<br>
