Nexus3.x 说明

功能介绍

Nexus3, 是一款支持仓库种类繁多的私服仓库管理工具,支持目前大众所知晓的仓库类型如:go、pypi、docker、maven、yum、git、helm、npm、apt …,且功能强大。为此解决了不同类型的仓库 统一管理 问题。

仓库类型

目前Nexus3 仓库类型,可以分为三种,即 hostedproxygroup 类型参考。

  • group: 即是多个仓库的集合,group中可 包涵多个 hosted, proxy, group 类型的仓库

    注意,在 group 中还存在优先级的关系,即示例图中,如 customaliyun 的docker仓库中多包涵了 centos:7 的镜像,那么在客户端使用 docker pull 拉取的是 custom 中的 centos7,原因为: “在nexus3 group仓库中使用为 自上而下 的匹配方式,当匹配后将 不再继续 向下匹配”,所以说我们在使用 “group"类型参考时还需要考虑一下,各个仓库的 优先级

    image-20210114180247413

  • proxy: 即是代理仓库,也叫缓存仓库, 示例原理: 。

    客户端请求 proxy 类型私服 如仓库中依赖存在即返回给客户端,如未存在就从proxy配置的远程仓库中拉取依赖返回给客户端,同时在 proxy 私服中进行缓存一份,当第二次访问时,即命中直接从本地 proxy 仓库返回

    未命名绘图

    • hosted: 即是用户自定义的参考

环境说明

  • 操作系统: Centos 7.7 (vm)
  • Docker 版本: 18.09.9
  • 代理工具: Nginx
  • Helm 版本: 3.x
  • Nginx: 1.16.1

使用 Docker 部署

建议部署 nexus3 的机器,应配置使用 lvm 逻辑卷 管理,方便在磁盘空间不足时可以添加磁盘进行 动态扩展

省略 docker 安装步骤和 os 初始化,这部分参考 链接

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
mkdir -p /application/nexus3/data  \
&& chmod 777 -R /application/nexus3    # 这里权限,出于安全考虑不应该设置这么大,我这里是开发环境使用就无所谓,生产环境应该酌情考虑。

docker run -dti \
--net=host --name=nexus3 \
--privileged=true --restart=always \
-e INSTALL4J_ADD_VM_PARAMS="-Xms4g -Xmx4g -XX:MaxDirectMemorySize=6g" \
-v /etc/localtime:/etc/localtime:ro \
-v /application/nexus3/data:/nexus-data \
sonatype/nexus3:3.27.0

检查是否正常启动

1
2
3
sleep 5 && docker logs --tail 100 nexus3 

netstat -lntp |grep 8081  # 端口是否监听

初始安装账号为 admin,初始密码在这个文件里面 /application/nexus3/data/admin.password (按照我的步骤来的话),剩下的就是会有一个初始化的过程 也就是让你重置 admin 的密码 和 是否开启匿名 功能 。

install

配置 nginx 反向代理

此步骤包涵配置nginx 反向代理,及初始化nexus docker私服

nginx 安装及 配置文件调优

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
yum install -y nginx  # 安装

useradd -M -s /sbin/nologin www  # 添加 http 服务专属用户

mv /etc/nginx/nginx.conf{,.bak} # 修改默认配置

cat > /etc/nginx/nginx.conf << EOF
user www www;
worker_processes auto;

error_log /var/log/error_nginx.log crit;
pid /var/run/nginx.pid;
worker_rlimit_nofile 51200;

events {
  use epoll;
  worker_connections 51200;
  multi_accept on;
}

http {
  include mime.types;
  default_type application/octet-stream;
  server_names_hash_bucket_size 128;
  client_header_buffer_size 32k;
  large_client_header_buffers 4 32k;
  client_max_body_size 0;
  client_body_buffer_size 4096m;
  sendfile on;
  tcp_nopush on;
  keepalive_timeout 600;
#  server_tokens off;
  tcp_nodelay on;

  fastcgi_connect_timeout 300;
  fastcgi_send_timeout 300;
  fastcgi_read_timeout 300;
  fastcgi_buffer_size 64k;
  fastcgi_buffers 4 64k;
  fastcgi_busy_buffers_size 128k;
  fastcgi_temp_file_write_size 128k;
  fastcgi_intercept_errors on;

  #Gzip Compression
  gzip on;
  gzip_buffers 16 8k;
  gzip_comp_level 6;
  gzip_http_version 1.1;
  gzip_min_length 256;
  gzip_proxied any;
  gzip_vary on;
  gzip_types
    text/xml application/xml application/atom+xml application/rss+xml application/xhtml+xml image/svg+xml
    text/javascript application/javascript application/x-javascript
    text/x-json application/json application/x-web-app-manifest+json
    text/css text/plain text/x-component
    font/opentype application/x-font-ttf application/vnd.ms-fontobject
    image/x-icon;
  gzip_disable "MSIE [1-6]\.(?!.*SV1)";

    log_format access_log_json '{ "@timestamp": "$time_local", '
'"remote_addr": "$remote_addr", '
'"referer": "$http_referer", '
'"request": "$request", '
'"status": $status, '
'"bytes": $body_bytes_sent, '
'"agent": "$http_user_agent", '
'"x_forwarded": "$http_x_forwarded_for", '
'"up_addr": "$upstream_addr",'
'"up_host": "$upstream_http_host",'
'"up_resp_time": "$upstream_response_time",'
'"request_time": "$request_time"'
' }';

    log_format json '{ "@timestamp": "$time_iso8601", '
                            '"time": "$time_iso8601", '
                            '"remote_addr": "$remote_addr", '
                            '"remote_user": "$remote_user", '
                            '"body_bytes_sent": "$body_bytes_sent", '
                            '"request_time": "$request_time", '
                            '"status": "$status", '
                            '"host": "$host", '
                            '"request": "$request", '
                            '"request_method": "$request_method", '
                            '"uri": "$uri", '
                            '"http_referrer": "$http_referer", '
                            '"body_bytes_sent":"$body_bytes_sent", '
                            '"http_x_forwarded_for": "$http_x_forwarded_for", '
                            '"http_user_agent": "$http_user_agent" '
                        '}';
  include conf.d/*.conf;
}
EOF

nginx -t  # 测试配置文件,有无错误.

配置 Docker 私服 & 配置 nginx 反向代理

创建 docker 专属 blob 存储卷

image-20200911091546155

image-20200911091722315

创建 docker hosted 类型仓库 image-20200911091224979

image-20200911091314192

image-20200911091944505

添加 docker proxy 类型仓库 image-20200914141738814

image-20200914141831948

图中使用代理仓库地址为: https://7bezldxe.mirror.aliyuncs.com

image-20200914141929471

创建 docker group 类型仓库 image-20200911092506337

image-20200914142809316

检查配置完成后,端口是否有监听,是否正常

1
2
3
4
netstat -lntp|egrep "8081|8082|8083"  # 如有以下三个端口存在即表示正常
tcp        0      0 0.0.0.0:8083            0.0.0.0:*               LISTEN      1393/java           
tcp        0      0 0.0.0.0:8081            0.0.0.0:*               LISTEN      1393/java           
tcp        0      0 0.0.0.0:8082            0.0.0.0:*               LISTEN      1393/java

开启 Docker认证功能

此功能不开启将导致 docker私服, 无法正常使用。

image-20200911110039179

image-20200911110151341

配置 nginx 反向代理

注意下列命令中带有 转义符号,应直接复制到终端执行即可。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
cat > /etc/nginx/conf.d/nexus3.conf << EOF
upstream nexus_web {
    server 127.0.0.1:8081;
}

upstream nexus_docker_get {
    server 127.0.0.1:8082;
}

upstream nexus_docker_put {
    server 127.0.0.1:8083;
}

server {
    listen 80;
    server_name idocker.io;
    access_log /var/log/idocker.io.log json;
    client_max_body_size 0;
    client_body_buffer_size 4096m;
    chunked_transfer_encoding on;
    set \$upstream "nexus_docker_put";
    if ( \$request_method ~* 'GET') {
        set \$upstream "nexus_docker_get";
    }
    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;
    }
}

server {
    listen 80;
    server_name repo.demo.com;
    client_max_body_size 0;
    proxy_max_temp_file_size 0;
    access_log /var/log/repo.demo.com.log access_log_json;
    location /download {
        root /application/download;
    }
    location / {
      proxy_pass http://nexus_web;
      proxy_set_header Host \$host;
      proxy_set_header X-Real-IP \$remote_addr;
      proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
    }
}
EOF

测试配置文件是否正常,进行配置的重载。

1
2
3
4
5
nginx -t 

service nginx restart \
&& service nginx status \
&& systemctl enable nginx # 启动并设置开机自启

最终所有仓库展示

image-20200911104933579

docker 私服客户端测试使用

在客户端 docker 容器的配置文件中添加 insecure-registries": ["idocker.io"] , 并配置对应 hosts记录, 示例中即 idocker.io

配置文件完整展示:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
cat /etc/docker/daemon.json
{
  "oom-score-adjust": -1000,
  "log-driver": "json-file",
  "log-opts": {
  "max-size": "100m",
  "max-file": "3"
  },
  "max-concurrent-downloads": 10,
  "max-concurrent-uploads": 10,
  "registry-mirrors": ["https://7bezldxe.mirror.aliyuncs.com"],
  "storage-driver": "overlay2",
  "insecure-registries": ["idocker.io"],
  "storage-opts": [
  "overlay2.override_kernel_check=true"
  ]
}

配置文件配好了后,进行重启一下 docker 服务进行测试。

1
2
3
4
5
6
service docker restart \
&& service docker status  # 重启服务

ping -c 3 idocker.io  # 检查对应host 是否有添加

docker login idocker.io -u admin -p 123456  # 登录私服,密码为你重置后的密码

测试 镜像的上传

1
2
3
docker tag sonatype/nexus3:3.27.0 idocker.io/sonatype/nexus3:3.27.0

docker push idocker.io/sonatype/nexus3:3.27.0

image-20200911110428718

Docker 部署,如何进行版本升级。

示例将 nexus3 版本升级至 3.29.2。笔者在使用 nexus3 一年多以来,老是发现xx版本有xxx漏洞,提示你尽快更新版本进行修复,所有这个升级版本的操作还是比较常用的,官方提供的最佳实践里面也说了,让你经常的更新 nexus3 的版本。

原容器启动命令

1
2
3
4
5
6
7
8
docker run -dti \
--net=host \
--name=nexus3 \
--privileged=true \
--restart=always \
-e INSTALL4J_ADD_VM_PARAMS="-Xms4g -Xmx4g -XX:MaxDirectMemorySize=6g" \
-v /etc/localtime:/etc/localtime \
-v /application/nexus3:/nexus-data sonatype/nexus3:3.28.1

升级步骤

  • neuxs3 容器版本 列表 查看

升级使用的镜像版本应使用具体版本号的镜像,建议不要使用 latest 镜像,这样在维护的时候不好区分。

更新步骤具体如下所示:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
docker stop nexus3
docker rename nexus3 nexus3_old

docker pull sonatype/nexus3:3.29.2 # 减少启动容器的时间,可先将镜像 download下来 。

docker run -dti \
--net=host \
--name=nexus3 \
--privileged=true \
--restart=always \
-e INSTALL4J_ADD_VM_PARAMS="-Xms4g -Xmx4g -XX:MaxDirectMemorySize=6g" \
-v /etc/localtime:/etc/localtime \
-v /application/nexus3:/nexus-data sonatype/nexus3:3.29.2


docker logs -f --tail 100 nexus3  # 查看启动有无报错

image-20210114092823923

新容器启动没有问题后,记得删除老容器即

1
docker rm -f nexus3_old

其他类型私服的配置

配置部署 Yum 私服

Nexus 具体配置项

创建 blob stores

image-20200910170348196

image-20200910170438617

创建 hosted yum 仓库 image-20200910170153343

image-20200910180549889

⚠️ 注意这里的 文件深度,会影响后期的 rpm 包依赖上传 , 下面图片中为截取官方文档的说明。

image-20200910180656801

RPM 依赖的上传配置

接下来我们来进行 测试上传 前的准备

示例使用 CentOS-7-x86_64-Everything-2003.iso 镜像中所有 rpm包,配置到 yum 私服中

1
2
3
4
5
mount -t auto CentOS-7-x86_64-Everything-2003.iso /mnt/  # 挂载镜像

mkdir -p /data/centos7/rpm-lists/   # 文件夹深度对应私服上的深度

\cp -a /mnt/Packages/*.rpm /data/centos7/rpm-lists/  # 将文件 copy 至上传文件夹下,因挂载的镜像为只读。此时我们也可以在上传文件夹下放置一些我们想上传到私服rpm依赖。

上传依赖至私服中

为防止账号密码泄露,可暂时关闭命令记录。

1
2
3
export HISTSIZE=0  # 关闭当前终端 命令记录。

for i in `ls`;do curl -v --user 'admin:123456' --upload-file /data/centos7/rpm-lists/"$i" http://192.168.1.9:8081/repository/yum-hosted/7/os/x86_64/"$i";done

执行完成上传后 等待 60秒或手动完成索引重建

image-20200910182853407

image-20200910182914592

Yum 私服 客户端使用

定义 yum 私服文件

注意下列命令中携带了 转义符,如配置了反向代理,可将主机地址指向 反向代理地址

yum-repo

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
mv /etc/yum.repos.d{,.bak}
mkdir -p /etc/yum.repos.d
cat > /etc/yum.repos.d/nexus.repo << EOF
[nexusrepo]
name=Nexus Repository
baseurl=http://192.168.1.9:8081/repository/yum-hub/\$releasever/os/\$basearch/
enabled=1
gpgcheck=0
EOF  # 注意 baseurl 地址

yum clean all 
yum makecache  # 缓存索引

image-20200910183110431

测试一下安装一个包

此包为我在上传前,放到 “上传文件夹"下的,所有在我的环境会有,也可以测试安装包替换为 vim

1
yum install -y kubectl  # or vim

配置部署 Helm 私服

Nexus 配置项记录

创建 helm 专属 blob stores

image-20200918103554963

创建 helm hosted 类型仓库

image-20200918103410484

image-20200918103456336

image-20200918103752200

image-20200918103955596

此处helm,未演示配置 proxy 类型的仓库了,其实现原理就是当客户端访问 nexus proxy 仓库时,如仓库中依赖存在即返回给客户端,如未存在就从proxy配置的远程仓库中拉取依赖返回给客户端,同时在 proxy 私服中进行缓存一份,当第二次访问时,即命中直接从本地 proxy 仓库返回。 nexus3 中proxy 仓库原理多是使用这个机制

Helm 上传依赖包配置

dashboard 界面上传

image-20200918145618916

image-20200918145646107

curl 命令上传

1
curl -u "USER_NAME":"USER_PASSWD" http://repo.demo.com/repository/helm-demo/ --upload-file ./"$UPLOADFILE" -v 

客户端使用

1
2
helm repo add  demo http://repo.demo.com/repository/helm-demo  # helm 3.x
helm repo update

配置部署 pypi 私服

Nexus 配置项记录

创建 pypi 专属 blob stores

image-20200918104237876

创建 pypi hosted 类型仓库

image-20200918104347358

创建 pypi group 类型仓库,并将上面创建的 hosted 仓库加入至组中

image-20200918104723703

配合完成后,即使用 group 地址

image-20200918104736891

Pypi 依赖上传配置

省略 dashboard 上传,同上 helm 一致,区别于选择仓库

命令上传

命令上传,依赖使用 twine 工具。目前 pypi 私服上传且支持 .tar.gz & .whl 两种类型的包

具体 文档参考

1
2
3
4
5
python3 setup.py sdist  # python 打包

pip install twine  # 安装上传工具

twine upload --repository-url http://repo.demo.com/repository/pypi-demo/ dist/*  -u ${USERKEY_USR} -p ${USERKEY_PSW}

pending。。