Sonatype Nexus3 搭建私有倉庫

Sonatype-Nexus3

Nexus是Sonatype提供的倉庫管理平台,Nuexus Repository OSS3能夠支援Maven、npm、Docker、YUM、Helm等格式數據的存儲和發布;並且能夠與Jekins、SonaQube和Eclipse等工具進行集成。
Nexus支援作為宿主和代理存儲庫的本地Maven/Docker存儲庫,可以直接將這些存儲庫暴露給客戶端工具;也可以以存儲庫組的方式暴露給客戶端工具,存儲庫組是合併了多個存儲庫的內容的存儲庫,能夠通過一個URL將多個存儲庫暴露給客戶端工具,從而便於用戶的使用。通過nexus自建能夠有效減少訪問獲取鏡像的時間和對頻寬使用,並能夠通過自有的鏡像倉庫共享企業自己的鏡像。

SSL證書

需要 2 個域名,一個用來代理 Nexus 管理面板,另一個用做 docker 倉庫,docker 需要單獨的埠

Nexus 前台:registry.jonty.top

Docker 倉庫:hub.jonty.top

自簽名證書

我們通過Nginx代理Nexus服務,需要先生成自簽名的SSL證書,通過內部DNS域名訪問(無需在docker pull的時候還要帶一個埠)

使用一鍵生成工具:ssl,兩個域名都要簽發證書

# 克隆倉庫
git clone //github.com/Fishdrowned/ssl.git
cd ssl
# 根據你的域名更改
/bin/bash ./gen.cert.sh hub.jonty.top 

PS:如果是打算做外網倉庫服務,可以直接申請一個免費的SSL證書(雲廠商都提供),本文使用內網域名,使用自簽名證書

[root@nexus3 ssl-master]# ls
ca.cnf  docs  flush.sh  gen.cert.sh  gen.root.sh  LICENSE  out  README.md
[root@nexus3 ssl-master]# cd out/
[root@nexus3 out]# ls
cert.key.pem  index.txt  index.txt.attr  index.txt.attr.old  index.txt.old  newcerts  root.crt  root.key.pem  serial  serial.old
[root@nexus3 out]# cd ..
[root@nexus3 ssl-master]# /bin/bash gen.cert.sh hub.jonty.top # 換成你的域名
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:'hub.jonty.top'
commonName            :ASN.1 12:'*.hub.jonty.top'
Certificate is to be certified until Jul 11 08:06:41 2024 GMT (730 days)

Write out database with 1 new entries
Data Base Updated

Certificates are located in:
lrwxrwxrwx. 1 root root 44 Jul 12 16:06 /root/docker/ssl-master/out/hub.jonty.top/hub.xxx.bundle.crt -> ./20220712-1606/hub.jonty.top.bundle.crt
lrwxrwxrwx. 1 root root 37 Jul 12 16:06 /root/docker/ssl-master/out/hub.jonty.top/hub.xxx.crt -> ./20220712-1606/hub.jonty.top.crt
lrwxrwxrwx. 1 root root 15 Jul 12 16:06 /root/docker/ssl-master/out/hub.jonty.top/hub.xxx.key.pem -> ../cert.key.pem
lrwxrwxrwx. 1 root root 11 Jul 12 16:06 /root/docker/ssl-master/out/hub.jonty.top/root.crt -> ../root.crt
[root@nexus3 ssl-master]# cd out/hub.jonty.top/
[root@nexus3 hub.jonty.top]# ls
20220712-1606  hub.jonty.top.bundle.crt  hub.jonty.top.crt  hub.jonty.top.key.pem  root.crt

阿里雲簽發

如果有域名,可以購買Aliyun免費ssl證書,一年有效期,可以有效避免自簽名證書不適用的問題

image-20220801155820025

申請完成後,下載Nginx證書並上傳到伺服器

image-20220801160226471

本地域名解析

Windows:C:\Windows\System32\drivers\etc\hosts

Linux:vi /etc/hosts

將以下解析加入,測試是否可以ping

192.168.2.xx hub.jonty.top
192.168.2.xx registry.jonty.top

服務端和客戶端都需要配置

部署

環境準備

安裝Docker-Engine

Install Docker Engine on CentOS | Docker Documentation

[root@nexus3 ~]# docker -v
Docker version 20.10.17, build 100c701
[root@nexus3 ~]# docker compose version
Docker Compose version v2.6.0

創建數據路徑並設置許可權

mkdir -p $PWD/nexus3/data 
chmod 777 $PWD/nexus3/data 
cd $PWD/nexus3

將生成的證書複製$PWD/nexus3/certs目錄下(2個域名的證書都需要)

[root@nexus3 hub.jonty.top]# cp hub.jonty.top.crt ~/nexus3/certs/
[root@nexus3 hub.jonty.top]# cp hub.jonty.top.key.pem ~/nexus3/certs/
[root@nexus3 hub.jonty.top]# cd ~/nexus3/certs/
[root@nexus3 certs]# ls
hub.jonty.top.crt hub.jonty.top.key.pem

docker-compose.yml

~/nexus3目錄下

version: "3.7"

services:
  nexus3:
    image: sonatype/nexus3:3.33.1
    container_name: nexus3
    restart: always
    privileged: true
    environment:
      - TZ=Asia/Shanghai
    volumes:
      - $PWD/data:/nexus-data
      
  nginx:
    image: nginx:1.21.1-alpine
    container_name: nginx
    restart: always
    environment:
      - TZ=Asia/Shanghai
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - $PWD/nginx.conf:/etc/nginx/nginx.conf:ro     # nginx配置
      - $PWD/certs:/etc/nginx/certs                    # SSL證書
      - $PWD/log:/var/log/nginx
    depends_on:
      - nexus3
    logging:
      driver: "json-file"
      options:
        max-size: "5g"  # 限制日誌大小

nginx.conf

在同目錄下創建nginx.confnginx配置文件

請參考ssl

worker_processes 4;
worker_rlimit_nofile 40000;

events {
    worker_connections 8192;
}

http {
    upstream nexus3_http {
        server nexus3:8081;
    }

    server{
        listen 80;
        server_name registry.jonty.top;
        return 301 //$server_name$request_uri;
    }

    server {
        listen 443 ssl;
        server_name registry.jonty.top; 
        
        # SSL
        ssl_certificate /certs/registry.jonty.top/registry.jonty.top.pem;
    	ssl_certificate_key /certs/registry.jonty.top/registry.jonty.top.key;
		
        client_max_body_size 5000m;  # 上傳大文件
		fastcgi_connect_timeout 300s;
        fastcgi_send_timeout 300s;
        fastcgi_read_timeout 300s;
        location / {
            proxy_pass //nexus3_http;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "Upgrade";
        }
    }

    upstream nexus_docker_get {
        server nexus3:8082;
    }
 
    upstream nexus_docker_put {
        server nexus3:8083;
    }
    
    server{
        listen 80;
        server_name hub.jonty.top;
        return 301 //$server_name$request_uri;
    }

    server {
        listen 443 ssl;
        server_name hub.jonty.top;
        # 證書
        ssl_certificate /certs/hub.jonty.top/hub.jonty.top.pem;
        ssl_certificate_key /certs/hub.jonty.top/hub.jonty.top.key;
        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;
        client_max_body_size 5000m;
        chunked_transfer_encoding on;
        set $upstream "nexus_docker_put";
        if ( $request_method ~* 'GET') {
            set $upstream "nexus_docker_get";
        }
        location / {
                proxy_pass //$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;
        }
    }
}

查看目錄

yum install -y tree
cd nexus3
tree -C -L 2
tree -C

image-20220805163921371

image-20220805164026553

運行

docker-compose up -d

image-20220712162731428

訪問://registry.jonty.top

Nexus初始化需要3~5min,初始化完成後可訪問

image-20220712163303455

使用

密碼配置

查看admin默認密碼:

[root@nexus3 nexus3]# cat data/admin.password
098fb8d9-e07b-4f7f-b498-806cdce1291d

image-20220712164027694

Docker存儲庫

創建Blob存儲

創建用於存放docker鏡像文件的存儲區域

image-20220712164443301

創建存儲庫

存儲庫有以下三種類型:

  • proxy:表示代理倉庫,請求包(package)的時候,如果本地有,它就從本地提供,如果本地沒有,則從代理地址下載到本地,然後提供這個包。

  • hosted:表示託管倉庫,一般用於推送開發的包到該倉庫。

  • group:表示倉庫組,它結合了proxy和hosted,能對外提供上述兩者中的包,對外的出口

image-20220712164651836

hosted:本地倉庫

創建hosted類型,用於存儲本地推送的鏡像

image-20220801170444372

埠設置為8083,對應nginx.conf配置nexus_docker_put

image-20220801170157413

proxy :代理倉庫

代理官方源://registry-1.docker.io

image-20220805164336262

代理阿里雲私有倉庫(可公開拉取):

image-20220805164414466

如果代理的私有庫需要授權

image-20220801170854550

group : 倉庫組

埠設置為8082,對應nginx.conf配置nexus_docker_get

編輯組成員,根據順序可排優先順序

image-20220805164454963

上傳docker鏡像

配置授信

使用自簽名證書需要配置此步驟

sudo vi /etc/docker/daemon.json

加入以下配置

{  
   "insecure-registries":["//hub.jonty.top"]
}

重啟docker

sudo systemctl restart docker

docker登錄私庫時提示 x509: certificate signed by unknown authority

登錄

[root@nexus3 nexus3]# docker login hub.jonty.top -u admin
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
//docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

推送鏡像

[root@nexus3 nexus3]# docker images
REPOSITORY        TAG             IMAGE ID       CREATED         SIZE
nginx             1.21.1-alpine   1318bf5f63b4   10 months ago   22.8MB
sonatype/nexus3   3.33.1          a0d390a200d2   10 months ago   655MB
[root@nexus3 nexus3]# docker tag nginx:1.21.1-alpine hub.jonty.top/nginx:1.21.1-alpine
[root@nexus3 nexus3]# docker push hub.jonty.top/nginx:1.21.1-alpine
The push refers to repository [hub.jonty.top/nginx]
45d993692050: Pushed
1ea998b95474: Pushed
95b99a5c3767: Pushed
fc03e3cb8568: Pushed
24934e5e6c61: Pushed
e2eb06d8af82: Pushed
1.21.1-alpine: digest: sha256:bd0aa91fe6a182db22032463c17644cd2ff3bbe415e7b84964283bba687acaa6 size: 1568

image-20220712170930285

拉取鏡像

注意,客戶端需要配置授信域名解析,如果開啟允許匿名拉取則不需授信,配置了路由器DNS則不需要配置hosts文件

[root@test ~]# cat /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

192.168.2.xx hub.jonty.top
192.168.2.xx registry.jonty.top
[root@test ~]# cat /etc/docker/daemon.json
{
  "insecure-registries": ["//hub.jonty.top"]
}
[root@test ~]# docker pull hub.jonty.top/mssql:2019-latest
2019-latest: Pulling from mssql
d5fd17ec1767: Already exists 
cf291b38357f: Pull complete 
af7e8d6f1719: Pull complete 
Digest: sha256:584a7fc7e2a378bdd4e8fe3bad36dae18e85527308193cb5c43d90863d7a7d4a
Status: Downloaded newer image for hub.jonty.top/mssql:2019-latest
hub.jonty.top/mssql:2019-latest

Gitlab-CI

在 Docker 容器中運行 CI/CD 作業|GitLab

[root@nexus3 ~]# cat ~/.docker/config.json
{
	"auths": {
		"//index.docker.io/v1/": {
			"auth": "am9udHltYXg6Sm9udHlNYXgzMjE="
		},
		"hub.jonty.top": {
			"auth": "YWRtaW46Z2N0bmV4dXMz"
		}
	}
}[root@nexus3 ~]# 
[root@nexus3 ~]# echo -n "admin:nexus3" | base64
YWRtaW46Z2N0bmV4dXMz

CI配置:

variables:
  DOCKER_AUTH_CONFIG: '{"auths": {"hub.jonty.top": {"auth": "YWRtaW46SGFyYm9yMTIzNDU="}}}'

設置匿名拉取

按需開啟,開啟則不需要配置以上授信部分

image-20220727093218720

NuGet存儲庫

上傳nuget包

Nexus默認已經創建好了Nuget的倉庫,並且是創建了3個不同類型的倉庫:nuget-group,nuget-hosted,nuget.org-proxy

image-20220712172140135

添加Nuget Realms

Nexus認證Nuget是通過Realms來認證

image-20220712172321065

獲取倉庫地址以及Nuget API Key

倉庫列表>複製地址

image-20220712172440616

獲取NuGet API Key

image-20220712172607085

推送本地NuGet包

dotnet nuget push .\abp.7.2.1.nupkg -k 238d37fc-9fae-335d-a812-29c2799d8f0e --source //registry.jonty.top/repository/nuget-hosted/
正在將 abp.7.2.1.nupkg 推送到 '//registry.jonty.top/repository/nuget-hosted/'...
  PUT //registry.jonty.top/repository/nuget-hosted/
  Created //registry.jonty.top/repository/nuget-hosted/ 288 毫秒
已推送包。

image-20220712172736234

配置本地NuGet包源

在VS中添加了本地源

image-20220712172917172

image-20220712173030239

新增Nuget代理

代理公網的私有源,如Nuget、Gitlab

啟用NuGet V3版本

image-20220805165042203

私有源授權image-20220801173138755

添加倉庫組

image-20220805165114055

NuGet V3

正常訪問nuget-group:

//registry.jonty.top/repository/nuget-group/

使用V3版本需要添加

//registry.jonty.top/repository/nuget-group/index.json

使用私有NuGet源

如果是代理私有庫,先刪除本地源

dotnet nuget list source
dotnet nuget remove source <NAME>

添加私有源

dotnet nuget add source //registry.jonty.top/repository/nuget-group/index.json -n nexus3 -u admin -p nexus3 --store-password-in-clear-text

清空本地nuget快取

dotnet nuget locals http-cache --clear
dotnet nuget locals global-packages --clear

當代理的源更新後,Nexus本地快取會導致無法找到最新包,可手動清理

image-20220801164922446

NPM存儲庫

NPM代理

官方源

//registry.npmjs.org

image-20220801175628966

私有庫授權:

image-20220801175743567

NPM倉庫組

image-20220805165359080

使用NPM代理

配置代理

npm i --legacy-peer-deps  -verbose

# 查看npm源
npm config get registry

# 註冊私有源
npm config set registry //registry.jonty.top/repository/npm-group

# 登錄私服
npm login registry="//registry.jonty.top/repository/npm-group/"  

npm cache clean --force

npm 新版本 -g需要替換為--location=global

# 查看yarn配置
yarn config list

# 配置私有源
yarn config set registry //registry.jonty.top/repository/npm-group/

yarn cache clean

查看密鑰

查看私服密鑰

[root@nexus3 ~]# cat ~/.npmrc
registry=//registry.jonty.top/repository/npm-group/
//registry.jonty.top/repository/npm-group/:_authToken=NpmToken.72b83be3-4b24-3dd1-850f-056cd78bb513

.npmrc

@delivery:registry=//registry.jonty.top/repository/npm-group/
//registry.jonty.top/repository/npm-group/:_authToken=NpmToken.612e0fd9-1526-3acd-9165-4e604d49a73d
always-auth=true

DevOps

目的

Deeper look into the basic CI/CD workflow

主要是配合Gitlab Runner CI/CD編譯打包

Runner執行流程

Runner執行流程

效果

後端項目從平均12min提升到3min以內,包括拉取程式碼、執行還原、編譯打包、推送等操作

前端項目從平均大於10min(30min也很常見)提升到7min以內,restore速度很快,主要是build操作緩慢,並且隨著依賴增多變得更慢

使用前

ci-before

使用後

ci-after

搞定~

撓屁股

其他問題

502 Bad Gateway

配置 nexus3 時使用 http 而非 https

no basic auth credentials

需要先 docker login 登錄

401 Unauthorized

docker login -u admin -p Harbor12345 hub.haifengat.com 登錄時報錯

img

參考文檔:

解決Error response from daemon: Get //: http: server gave HTTP response to HTTPS client_SerryYang的部落格-CSDN部落格

docker登錄私庫時提示 x509: certificate signed by unknown authority_舟行於無涯之海的部落格-CSDN部落格_docker login x509