Nexus使用小记

Nexus使用小记

Nexus(全称为Sonatype Nexus Repository)是一个软件存储库管理器。可以拿来做Docker私服、Maven私服等等。

这篇文章主要关注其作为Docker私服和Docker Hub镜像加速的功能。

Nexus分

  • Sonatype Nexus Repository OSS
  • Sonatype Nexus Repository Pro

后者要钱。所以我们用OSS。

另外,本篇文章我们会使用Docker的方式安装Nexus。因为更加方便简单,也是大多数教程的选择。

目标

  1. 建立一个内网私有镜像仓库
  2. 缓存从Docker Hub下载的镜像,加速内网其他机器的拉取

环境

  • Nexus服务器:192.168.81.198(debian8-hyperv,Docker version 27.5.1, build 9f9e405)
  • 测试客户端:192.168.81.190(debian-hyperv,Docker version 27.2.0, build 3ab425)

都是Debian 12,都安装并配置了sudo,都把当前用户(普通用户,非root)加到了docker用户组里。

另外,你还得有代理工具。

提示

如果你需要安装Docker,那你可能需要配置APT代理。

如果你需要拉取Nexus镜像,那你需要配置docker pull代理

过程记录

1、安装Nexus

参考:https://hub.docker.com/r/sonatype/nexus/

1
2
3
4
5
6
7
8
9
10
11
12
sudo mkdir -p /data/nexus # 创建数据文件夹
sudo chown -R 200 /data/nexus # 更改文件夹所有者

docker run \
-d \
--name nexus \
--restart always \
-p 8081:8081 \
-p 8082:8082 \
-p 8083:8083 \
-v /data/nexus:/nexus-data \
sonatype/nexus3:3.76.1 # 其中8081是Nexus的Web端口,其他两个端口后面会讲做什么用

登录http://Nexus服务器地址:8081,就可以看到如下页面了:

image-20250202040147803

值得一提的是,这个“Loading…”时间会很长,而且Loading结束后也只会显示如下内容:

image-20250202040239772

这是因为我们还没有给Nexus本身设置代理,等设置了代理以后就不太一样了。

2、Nexus基本设置

点击右上角的“Sign in”,会显示一个登录框,这里我们用账号admin登录,密码存储在容器内/nexus-data/admin.password文件里,如果你刚刚跟我一样设置了/data/nexus为数据文件夹,那么可以直接:

1
cat /data/nexus/admin.password

登陆后会显示设置向导:

image-20250202040629891

然后要你重设密码。

重点是配置匿名访问这一步,需要“Enable anonymous access”(允许匿名访问)。

image-20250202040725956

然后就是配置HTTP代理了,点击左上方齿轮图标,然后选左侧“System”的“HTTP”。勾选“Enable HTTP proxy”和“Enable HTTPS proxy”,并填好你代理服务器的IP和端口,然后保存。

image-20250202041409960

设置完以后你可以点击齿轮左侧的盒子图标,这时候“Loading…”应该会快点,而且会显示一些其他东西:

image-20250202041546931

3、激活Docker Bearer Token Realm

去“Realms”中将“Docker Bearer Token Realm”激活。

image-20250202045751815

4、创建Blob Store

Blob Store其实就像一个文件夹,其实都存到一起也可以,但是还是分开来更清晰。

image-20250202041801312

创建三个,一个叫docker-hub-proxy,一个叫docker-hosted,一个叫docker-all

image-20250202041945847

image-20250202042008231

image-20250202050806822

5、创建Repository(仓库)

简要介绍

Nexus的仓库分三种:

  • proxy,代理仓库
  • hosted,本地仓库
  • group,组仓库(其实就是把其他仓库进行一个聚合)

image-20250202042052807

docker (proxy)类型的仓库

首先创建docker (proxy)类型的仓库,并如下设置:

image-20250202044900637

image-20250202042720992

其中允许匿名访问是比较重要的,“Enable Docker V1 API”这个你开不开都可以,“HTTP Authentication”里填的是你Docker Hub的用户名密码,因为匿名用户拉取镜像有限制。另外Remote Storage填的URL其实就是你docker pull失败时显示的URL(**但是要去掉v2/**):

image-20250202043030909

创建仓库后,你就可以测试一下了。我们来到测试机(192.168.81.190)然后将/etc/docker/daemon.json修改成这个样子:

image-20250202043431884

其中insecure-registries主要是为了不让他用HTTPS,registry-mirrors是告诉Docker这个地址是个镜像仓库。另外,registry-mirrors的地址来自于这里:

image-20250202045404627

然后:

1
2
sudo systemctl daemon-reload
sudo systemctl restart docker

可以看到成功了:

image-20250202045102343

并且如果你去Nexus中查看,也会看到相关内容:

image-20250202045155915

image-20250202045211387

其实到这步为止,你就已经能够把Nexus当作一个镜像加速器了。

但是现在还不能push。而且之前的8082和8083也没有用到。另外daemon.json中的repository/docker-hub-proxy/后缀有点丑,能不能去掉?别急,后面会回答这些问题。

docker (hosted)类型的仓库

image-20250202050549993

这个仓库的作用就是存储一些我们构建的Docker镜像,只存在Nexus中,不传到互联网上。

docker (group)类型的仓库

image-20250202050929844

其中重点是把docker-hosteddocker-hub-proxy加入到组中。

现在你大概就能猜到docker (group)仓库的含义了。没错,他就是聚合其他的仓库,使之看上去像一个仓库。

也就是docker-hosteddocker-hub-proxy中的所有内容,同样也会出现在docker-all中。

所以,以后,我们所有的docker pull操作都应该来自于docker-all而不是之前的docker-hub-proxy因为,我们要pull的镜像既有可能是我们自己构建的,也有可能是来自Docker Hub的。

关于端口

好的,现在回过头来说明8082和8083端口的事。

第一,8083端口(docker-all用)主要是为了简洁,我们现在直接使用http://192.168.81.198:8081/repository/docker-all/也可以。但是我们想去掉后面的路径后缀,在daemon.json中使用http://192.168.81.198:8083/

第二,8082端口(docker-hosted用)是为了push。你可能已经注意到了,我们需要从docker-all拉取,往docker-hosted推送,因为前者只是一个group,一个聚合视图,而不是一个实际的仓库。(其实往group推也是可以的,但那是Nexus Pro的功能)

好,现在我们知道了需要往docker-hosted推,那不能直接使用http://192.168.81.198:8081/repository/docker-hosted/这个URL吗?这样不是省一个端口吗?

答案是:不行

让我们先做个小实验,docker login一个不存在的地址:

image-20250202052512320

肯定是失败了的,但失败不重要,我们要注意上下内容的变化。可以看到我们给出的是一个完整的URLhttp://baidu.com:8765/abc/def/,协议方式是HTTP,路径参数是/abc/def/。但是下面在请求的时候使用了https://baidu.com:8765/v2/,协议方式是HTTPS,路径参数是/v2/

也就是说,对于我们给的URL,它只看了主机地址:端口这部分,其他都不管了。

所以我们docker login http://192.168.81.198:8081/repository/docker-hosted/这个也会失败:

image-20250202054322927

可以看到,原有的路径参数没了,所以失败了。至于这里为啥没变成HTTPS,那是因为我们刚刚设置过daemon.jsoninsecure-registries了。

所以我们现在新增了一个端口,那就是8082。这样就可以使用http://192.168.81.198:8082/v2/了。

6、配置测试机并测试

在理解了以上内容后,我们把测试机的/etc/docker/daemon.json改成这样:

image-20250202054754984

可以看到,其中已经没有8081的事了。

同样,重启Docker:

1
2
sudo systemctl daemon-reload
sudo systemctl restart docker
1
docker login 你的Nexus服务器的地址:8082

image-20250202055044224

测试一下拉取:

image-20250202055128557

编写Dockerfile并推送:

1
2
3
FROM alpine

CMD ["echo","Hello Nexus!!!"]

image-20250202055512646

可以看到docker-all中已经有了对应文件:

image-20250202055655997

然后,再删除本地镜像并拉取运行:

image-20250202055853682

总结

总体来说,我认为Sonatype Nexus Repository确实挺不错,功能全面而且方便。

如果未来有机会,我也会尝试把它作为Maven仓库或者NPM仓库看看。

参考