# 二，使用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>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://darren.gitbook.io/project/devops/kai-yuan-cang-ku-nexus/er-shi-yong-nexus3-pei-zhi-docker-si-you-cang-ku.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
