Nexus3多类型开源私有化仓库

  • 说明:

    • 建议机器配置,官方建议4核心

3.1 基础配置

3.1.1 创建容器

  • 操作如下

    • 创建挂载目录并授权
    mkdir data && chmod 777 data
    • docker-compose.yaml
    version: "3.5"
    services:
    nexus:
      image: sonatype/nexus3:3.72.0
      container_name: nexus3
      restart: on-failure
      ports:
        - '8081:8081'
        - '8001:8001'
        - '8002:8002'
        - '8003:8003'
        - '8004:8004'
      environment:
        TZ: Asia/Shanghai
        INSTALL4J_ADD_VM_PARAMS: "-Xms256m -Xmx512m -XX:MaxDirectMemorySize=512m -Djava.util.prefs.userRoot=/nexus-data/javaprefs"
      volumes:
        - ./data:/nexus-data
    • 创建容器
    docker-compose up -d

3.1.2 页面访问

  • 操作如下

    • 访问 http://192.168.26.21:8081
    • 点击右上角 Sign in 登陆,默认账号admin,密码见 data/admin.password ,之后会让重新设置密码
    • 初始设置,禁止匿名用户访问
  • 小问题处理

    • 访问时会发现 Welcome 界面加载有点慢,查看日志有以下信息
    org.apache.http.conn.ConnectTimeoutException: Connect to sonatype-download.global.ssl.fastly.net:443 [sonatype-download.global.ssl.fastly.net/74.86.151.167] failed: Connect timed out
    • 关闭路径: 设置 —> System -> Capabilities -> Outreach: Management ,选择 Disable

3.1.3 创建存储

  • 操作如下

    • 以 docker 的为例,创建一个用于存储镜像的空间

    注意:存储类型可选择 file(本地磁盘) 和 S3(亚马逊对象存储) ,选择第一种即可

3.4 Docker 仓库

  • 仓库类型简介
    • hosted:本地类型,存放自定义镜像作为私有仓库
    • proxy:代理类型,负责拉取私仓没有的第三方镜像
    • group:是一个聚合类型,将私仓和代理仓聚合作为一个整体对外提供服务

3.4.1 Hosted 类型

  • 操作如下

    • 路径:设置 -> Repositories –> Create repository –> docker(hosted)
    # 选项说明(不提及的保留默认设置)
    1、Name  # 定义一个名称 docker-hosted
    2、Repository Connectors # HTTP 8001 允许 docker 客户端直接连接到 docker-hostsed 仓库
    3、Enable Docker V1 API # Docker registry 默认使用的是 API v2, 但是为了兼容性,可以勾选启用 API v1
    4、Blob Store # 选择前面创建的 dockerStore
    5、Deployment Policy # Allow redeploy 允许重复发布

3.4.2 Proxy 类型

  • 操作如下

    • 路径: 设置 -> Repositories –> Create repository –> docker(proxy)
    # 参数说明(不提及的保留默认设置)
    1、Name  # 定义一个名称 docker-proxy
    2、Repository Connectors # 端口不填 允许 docker 客户端直接连接到 docker-proxy 仓库
    3、Enable Docker V1 API # Docker registry 默认使用的是 API v2, 但是为了兼容性,可以勾选启用 API v1
    4、Remote Storage # DaoCloud 的容器加速:http://f1361db2.m.daocloud.io
    5、Docker Index # Use proxy registry
    6、Blob Store # 选择前面创建的 dockerStore

3.4.3 Group 类型

  • 操作如下

    • 路径: 设置 -> Repositories –> Create repository –> docker(group)
    # 参数说明(不提及的保留默认设置)
    1、Name  # 定义一个名称 docker-group
    2、Repository Connectors # HTTP 8003 允许 docker 客户端直接连接到 docker-group 仓库
    3、Enable Docker V1 API # Docker registry 默认使用的是 API v2, 但是为了兼容性,可以勾选启用 API v1
    4、Blob Store # 选择前面创建的 dockerStore
    5、Member repositories # 添加组成员,按序添加前面创建的 hsoted 和 proxy
    • 安全设置,将 Docker Bearer Token Realm 添加到活跃区
    # 如不勾选此选项,则无法使用 Nexus 加速镜像拉取,在使用 Nginx 代理中可看到日志如下,出现 401/404 错误
    "HEAD /v2/nginx/manifests/1.18 HTTP/1.1" 404 0 "-" "docker/20.10.21 
    "GET /v2/ HTTP/1.1" 401 113 "-" "docker/20.10.21 go/go1.18.7
    # 最直观现象就是不能拉取镜像,有以下提示
    $ docker pull registry.xxx.com/nginx:latest
    Error response from daemon: manifest for registry.xxx.com/nginx:latest not found: manifest unknown: manifest unknown

3.4.4 使用验证

  • 操作如下(准备 Docker + Nginx 环境)

    • Group 功能正常是要收费的,不能直接用 8003 端口。因此需要结合 Nginx 去实现拉取和推送的端口统一
  • 在nginx配置域名 registry.xxx.com.conf

    # 拉取镜像通过 group
    upstream nexus_docker_get {
      server 192.168.26.21:8003;
    }
    # 推送镜像通过 host
    upstream nexus_docker_put {
      server 192.168.26.21:8001;
    }
    server {
      listen 80;
      listen 443 ssl;
      server_name registry.xxx.com;
      access_log logs/registry_access.log;
      # 证书
      ssl_certificate certs/xxx.com.crt;
      ssl_certificate_key certs/xxx.com.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;
      # 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;
      }
    }
    • 推拉镜像测试
    # 登陆自建仓库
    docker login -u admin -p 123 registry.xxx.com
    # 通过私仓拉取镜像,发现proxy和group仓库都能看到缓存的mysql:8.0镜像
    docker pull registry.hukanfa.com/mysql:8.0
    # 拉取官方渠道镜像,打标签后,再推送到自建仓库,发现hosted仓库有该镜像
    docker pull nginx:1.18
    docker tag nginx:1.18 registry.hukanfa.com/nginx:1.18
    docker push registry.hukanfa.com/nginx:1.18

3.5 Maven 仓库

3.5.1 前置配置

  • 操作如下

    • 系统默认创建有以下仓库
    • 默认设置不符合要求,用不到全删掉重新创建
    • 创建 Maven Blob 存储

3.5.2 Hosted 类型

  • 操作如下

    • 路径:设置 -> Repositories –> Create repository –> maven2(hosted)
    # 选项说明(不提及的保留默认设置)
    1、Name  # 定义一个名称 maven-hosted
    2、Blob Store # mavenStore
    3、Deployment Policy # Allow redeploy 允许重复发布
    
    # Maven2:这里有三种方式 Releases、SNAPSHOT、Mixed 保持默认
    Releases: 一般是已经发布的 Jar 包
    Snapshot: 未发布的版本
    Mixed:混合的

3.5.3 Proxy 类型

  • 操作如下

    • 路径:设置 -> Repositories –> Create repository –> maven2(proxy)
    # 选项说明(不提及的保留默认设置)
    1、Name  # 定义一个名称 maven-proxy
    2、Proxy.Remote Storage # https://repo1.maven.org/maven2/
    2、Blob Store # mavenStore
    
    ## 阿里云仓库
    # 代理仓库
    https://maven.aliyun.com/repository/central
    # 公共仓库
    https://maven.aliyun.com/repository/public

3.5.5 Group 类型

  • 操作如下

    • 路径:设置 -> Repositories –> Create repository –> maven2(group)
    # 选项说明(不提及的保留默认设置)
    1、Name  # 定义一个名称 maven-group
    2、Blob Store # mavenStore
    3、Group # 将左边可选的 2 个仓库,添加到右边的 members 下
    • 获取仓库地址 http://192.168.26.21:8081/repository/maven-group/

3.5.6 使用验证

  • 操作如下(准备 Jdk + Maven 环境)

    • 调整配置增加私仓及私仓认证信息
    ## ../maven/conf/settings.xml
    # 注释调默认的mirror配置,添加以下mirror配置
    <mirrors>
      ...
      <mirror>
        <id>nexus</id>
        <mirrorOf>*</mirrorOf>
        <name>nexus</name>
        <url>http://192.168.26.21:8081/repository/maven-group/</url>
      </mirror>
    </mirrors>
    # 增加私仓认证信息
    <servers>
      ...
      <server>
        <id>nexus</id>
        <username>admin</username>
        <password>123</password>
      </server>
    </servers>
    • 拉取测试 java 项目进行编译
    # 开源项目地址,仅测试用
    wget https://gitee.com/hukanfa/springboot-helloworld/repository/archive/master.zip
    unzip master.zip && cd springboot-helloworld-master
    # 编译
    mvn clean install -N -U -Dmaven.test.skip=true
    • 此时,在 Nexus 界面浏览 maven-group 仓库可以看到下载的依赖,路由 local -> group -> proxy

3.6 Python 仓库

  • 前置配置

    • 创建 Python Blob 存储

3.6.1 Hosted 类型

  • 操作如下

    • 路径:设置 -> Repositories –> Create repository –> pypi(hosted)
    # 选项说明(不提及的保留默认设置)
    1、Name  # 定义一个名称 python-hosted
    2、Blob Store # pythonStore
    3、Deployment Policy # Allow redeploy 允许重复发布

3.6.2 Proxy 类型

  • 操作如下

    • 路径:设置 -> Repositories –> Create repository –> pypi(proxy)
    # 选项说明(不提及的保留默认设置)
    1、Name  # 定义一个名称 python-proxy
    2、Remote storage # 代理仓库地址 https://pypi.tuna.tsinghua.edu.cn/
    3、Blob Store # pythonStore
    
    # 其他代理地址,这里如果想配置多个代理可以创建多个proxy,可根据渠道命名
    官方 https://pypi.python.org/pypi/
    阿里云 https://mirrors.aliyun.com/pypi/
    中国科技大学 https://pypi.mirrors.ustc.edu.cn/
    豆瓣 https://pypi.douban.com/
    清华大学 https://pypi.tuna.tsinghua.edu.cn/
    中国科学技术大学 https://pypi.mirrors.ustc.edu.cn/

3.6.3 Group 类型

  • 操作如下

    • 路径:设置 -> Repositories –> Create repository –> pypi(group)
    # 选项说明(不提及的保留默认设置)
    1、Name  # 定义一个名称 python-group
    2、Blob Store # pythonStore
    3、Group # 将左边可选的 2 个仓库,添加到右边的 members 下
    • 获取仓库地址 http://192.168.26.21:8081/repository/python-group/
    # 注意:使用时需要在group地址后再加simple,最终使用地址如下
    http://192.168.26.21:8081/repository/python-group/simple

3.6.4 使用验证

  • 操作如下(准备 Python + pip 环境)

    • 通过pip命令随便安装一个python包,指定代理地址即可
    # 如果设置了验证则需要输入用户名和密码
    pip install delorean --trusted-host 192.168.26.21  -i http://192.168.26.21:8081/repository/python-group/simple
    • 浏览 maven-group 仓库可以看到下载的包
    • 配置pip.conf用户级环境,就不需要每次执行编译的时候指定私服地址了
    ## 创建目录
    mkdir ~/.pip
    
    ## 方式一:常规配置,如果有验证则需要输入账号密码
    cat > ~/.pip/pip.conf << EOF
    [global]
    timeout = 60
    trusted-host =  192.168.26.21
    index-url = http://192.168.26.21:8081/repository/python-group/simple
    EOF
    
    ## 方式二:携带账号密码,有安全风险建议仅测试用
    cat > ~/.pip/pip.conf << EOF
    [global]
    timeout = 60
    trusted-host =  192.168.26.21
    index-url = http://admin:123@192.168.26.21:8081/repository/python-group/simple
    EOF
    
    ## 下载包测试
    pip install django
    • 通过环境变量注入
    # 声明环境变量,演示时需要删掉 rm -f ~/.pip/pip.conf 保证实现效果
    export PIP_INDEX_URL=http://admin:123@192.168.26.21:8081/repository/python-group/simple
    export PIP_TRUSTED_HOST=192.168.26.21
    
    ## 下载包测试
    pip install plotly

3.7 Npm 仓库

  • 前置配置

    • 创建 Npm Blob 存储

3.7.1 Hosted 类型

  • 操作如下

    • 路径:设置 -> Repositories –> Create repository –> npm(hosted)
    # 选项说明(不提及的保留默认设置)
    1、Name  # 定义一个名称 npm-hosted
    2、Blob Store # npmStore
    3、Deployment Policy # Allow redeploy 允许重复发布

3.7.2 Proxy 类型

  • 操作如下

    • 路径:设置 -> Repositories –> Create repository –> npm(proxy)
    # 选项说明(不提及的保留默认设置)
    1、Name  # 定义一个名称 npm-proxy
    2、Remote storage # 代理地址 https://registry.npmmirror.com/
    3、Blob Store # npmStore
    
    # 其他代理地址,这里如果想配置多个代理可以创建多个proxy,可根据渠道命名
    官方 https://registry.npmjs.org
    淘宝源 https://registry.npmmirror.com/
    腾讯云 https://mirrors.cloud.tencent.com/npm/
    华为 https://repo.huaweicloud.com/repository/npm/
    清华大学 https://mirrors.tuna.tsinghua.edu.cn/npm/
    中国科学技术大学 https://mirrors.ustc.edu.cn/npm/

3.7.3 Group 类型

  • 操作如下

    • 路径:设置 -> Repositories –> Create repository –> npm(group)
    # 选项说明(不提及的保留默认设置)
    1、Name  # 定义一个名称 npm-group
    2、Blob Store # npmStore
    3、Group # 将左边可选的 2 个仓库,添加到右边的 members 下
    • 获取仓库地址 http://192.168.26.21:8081/repository/npm-group/
    • 安全设置,将 npm Bearer Token Realm 添加到活跃区
    # 不添加将会有以下报错
    Unable to authenticate, need: BASIC realm="Sonatype Nexus Repository Manager" 

3.7.4 使用验证

  • 操作如下(准备 Nodejs 环境)

    • 使用私服
    # 设置默认仓库为私服
    npm config set registry http://192.168.26.21:8081/repository/npm-group/
    npm config get registry
    # 登陆私服 --always-auth 永久有效
    npm login --registry=http://192.168.26.21:8081/repository/npm-group/ --always-auth
    # 登陆后,相关认证信息存在 ~/.npmrc
    registry=http://192.168.26.21:8081/repository/npm-group/
    //192.168.26.21:8081/repository/npm-group/:_authToken=NpmToken.bca28e13-43c4-3ee1-82b7-4d949d094b26
    • 项目编译实战
    # 下载 demo 项目
    wget https://gitee.com/hukanfa/nodejs-demo/repository/archive/master.zip
    # 解压并进入项目
    unzip master.zip && cd nodejs-demo-master/
    # 执行依赖包安装
    npm install
    • 浏览 npm-group 可以看到下载的包

3.8 Yum 仓库

  • 前置配置

    • 创建 Yum Blob 存储
    • 开启 Anonymous Access 权限
    # 若不开启,客户机配置的私仓在执行yum安装时会报错 401 ,如下
    $ yum makecache
    - Status code: 401 for http://192.168.26.21:8081/repository/yum-group/9/BaseOS/x86_64/os/repodata/repomd.xml (IP: 192.168.26.21)
    Error: Failed to download metadata for repo 'baseos': Cannot download repomd.xml: Cannot download repodata/repomd.xml: All mirrors were tried

3.8.1 Hosted 类型

  • 操作如下

    • 路径:设置 -> Repositories –> Create repository –> yum(hosted)
    # 选项说明(不提及的保留默认设置)
    1、Name  # 定义一个名称 yum-hosted
    2、Repodata Depth # 2
    3、Blob Store # yumStore
    4、Deployment Policy # Allow redeploy 允许重复发布

3.8.2 Proxy 类型

  • 操作如下

    • 路径:设置 -> Repositories –> Create repository –> yum(proxy)
    # 选项说明(不提及的保留默认设置) - Rockylinux
    1、Name  # 定义一个名称 yum-proxy
    2、Remote storage # 代理 https://mirrors.aliyun.com/rockylinux
    3、Blob Store # yumStore
    
    # 其他代理地址,这里如果想配置多个代理可以创建多个proxy,可根据渠道命名
    官方 http://dl.rockylinux.org/$contentdir
    上海交通大学 https://mirrors.sjtug.sjtu.edu.cn/rocky
    腾讯云 https://mirrors.cloud.tencent.com/rocky/
    阿里云 https://mirrors.aliyun.com/rockylinux
    南京大学 https://mirror.nju.edu.cn/rocky
    西安交大:https://mirrors.xjtu.edu.cn/rocky/
    中国科学技术大学 https://mirrors.ustc.edu.cn/rocky

3.8.3 Group 类型

  • 操作如下

    • 路径:设置 -> Repositories –> Create repository –> yum(group)
    # 选项说明(不提及的保留默认设置)
    1、Name  # 定义一个名称 yum-group
    2、Blob Store # yumStore
    3、Group # 将左边可选的 2 个仓库,添加到右边的 members 下
    • 获取仓库地址 http://192.168.26.21:8081/repository/yum-group/

3.8.4 使用验证

  • 操作如下(准备 Rockylinux 环境)

    • 创建缓存
    ## 先将源替换为阿里云,如果代理是其他源同样操作
    # 备份
    cp -ar /etc/yum.repos.d /etc/yum.repos.d.bak
    # 替换
    sed -e 's|^mirrorlist=|#mirrorlist=|g' \
      -e 's|^#baseurl=http://dl.rockylinux.org/$contentdir|baseurl=https://mirrors.aliyun.com/rockylinux|g'
    /etc/yum.repos.d/rocky*.repo
    
    # 将阿里云的源替换为 group 私仓,也可以在步骤2一步替换到位
    sed -i 's|baseurl=https://mirrors.aliyun.com/rockylinux|baseurl=http://192.168.26.21:8081/repository/yum-group|' /etc/yum.repos.d/rocky*.repo
    
    # 更新缓存
    yum clean all
    yum makecache
    • 浏览 yum-group 可以看到缓存的元数据文件
    • 尝试安装 telnet 工具
    # 如果之前已安装,可以执行卸载命令 yum -y remove telnet
    yum -y install telnet

3.9 Apt 仓库

  • 前置配置

    • 创建 Apt Blob 存储

3.9.1 Hosted 类型

  • 操作如下

    • 路径:设置 -> Repositories –> Create repository –> apt(hosted)
    # 选项说明(不提及的保留默认设置)
    1、Name  # 定义一个名称 apt-hosted
    2、Distribution # 本地的就自定义 testing
    3、SignIng Key && Passphrase # key获取方式请看下面  123
    3、Blob Store # aptStore
    4、Deployment Policy # Allow redeploy 允许重复发布
    • 获取 SignIng Key && Passphrase
    ## 通过如下命令设置,过程中会要求输入密码(Passphrase)
    # 需要提前安装 apt install pinentry-curses -y
    apt-get update
    apt-get install gpg
    
    ## 密钥相关
    # 官网参考 https://help.sonatype.com/en/apt-repositories.html
    # 生成GPG密钥对,其他提示默认即可,注意有个输入密码的提示 passphrase: xxx
    gpg --gen-key
    # 查看公钥 , 获取 <gpg key Id>
    gpg --list-keys
    # 导出公钥(请保存),后续其他机器想从 apt-hosted 拉取内部包需要公钥 --export <gpg key Id>
    gpg --armor --output public.gpg.key --export 1FCBFEF639235C505929A2AF5CAECD52B8B57E62
    # 导出私钥 --armor 以 ASCII 格式输出,将私有 PGP 密钥放入 Signing Key 字段中
    gpg --armor --output private.gpg.key --export-secret-key 1FCBFEF639235C505929A2AF5CAECD52B8B57E62

    3.9.2 Proxy 类型

  • 操作如下,路径:设置 -> Repositories –> Create repository –> apt(proxy)

    • Debian
    # 选项说明(不提及的保留默认设置)
    1、Name  # 定义一个名称 apt-proxy-debian
    2、Distribution # 发行版本代号 Trixie,Bookworm,Bullseye,Buster,jessie,stretch
    3、Remote storage # 代理 https://mirrors.tuna.tsinghua.edu.cn/debian/
    4、Blob Store # aptStore
    
    ## 补充
    # 关于发行版本代号相关信息可查看官网
    https://www.debian.org/releases/
    # 其他代理
    阿里云 https://mirrors.aliyun.com/debian/
    中国科技大学 https://mirrors.ustc.edu.cn/debian/
    华为云 https://mirrors.huaweicloud.com/debian/
    163  https://mirrors.163.com/debian/
    腾讯云 http://mirrors.cloud.tencent.com/debian/
    上海交大 https://mirror.sjtu.edu.cn/debian/
    • Ubuntu
    # 选项说明(不提及的保留默认设置)
    1、Name  # 定义一个名称 apt-proxy-ubuntu
    2、Distribution # 发行版本代号 precise,trusty,xenial,bionic,focal
    3、Remote storage # 代理 https://mirrors.tuna.tsinghua.edu.cn/ubuntu/
    4、Blob Store # aptStore

3.9.3 使用验证

  • 操作如下(准备debian环境)

    • 下载deb包,并将它上传到 apt-hosted
    # 创建包存放目录
    hukanfa@hukanfa:~$ mkdir packages &&  cd packages
    hukanfa@hukanfa:~/packages$
    # 可以将 apt-proxy-debian 私仓添加到源文件 ,或者直接使用清华等三方源下载
    echo "deb http://nexus.xxx.com/repository/apt-proxy-debian testing main" > /etc/apt/sources.list
    apt-get update
    # 下载指定版本的deb包
    hukanfa@hukanfa:~/packages$ apt download perl=5.40.0-7
    获取:1 http://nexus.xxx.com/repository/apt-proxy-debian testing/main amd64 perl amd64 5.40.0-7 [267 kB]
    已下载 267 kB,耗时 2秒 (155 kB/s)
    hukanfa@hukanfa:~/packages$ ls
    perl_5.40.0-7_amd64.deb
    ## 将下载的deb包上传到 apt-hosted 仓库 
    curl -v -u "admin:123" -X POST -H "Content-Type: multipart/form-data" --data-binary "@./perl_5.40.0-7_amd64.deb" http://nexus.xxx.com/repository/apt-hosted/
    # --data-binary "@/home/yourusername/path/to/perl_5.40.0-7_amd64.deb" 这里也可以全路径
    ## 顺便提下一条命令批量上传指定目录下的所有deb包,或者使用下面脚本也行
    find . -name "*.deb" -exec curl -v -u "admin:123" -X POST -H "Content-Type: multipart/form-data" --data-binary "@{}" http://nexus.xxx.com/repository/apt-hosted/ \;
    • upload_dep.sh 通过脚本单个或批量上传
    #!/bin/bash
    ## 前置函数
    # 判断命令执行状态 eg: func_check_cmdStatus "远程连接"
    function func_check_cmdStatus(){
    if [ $? -ne 0 ];then
      echo "执行${1}失败,请核查"
      exit 1
    else
      echo "执行${1}成功"
    fi
    }
    
    ## 接收传参
    # 如果是目录路径则会将该路径下的所有.deb包上传(/path/packages)
    # 如果是文件则只上传单个文件(aaa.deb 或者 /path/aa.deb)
    var_input_args=$1
    # 传参标签,如果是路径则为 dir,文件则为 file,默认为空
    var_args_type=""
    # 临时日志文件
    var_logs_file="/tmp/upload_deb.log"
    # 私仓相关信息,根据需求也可以设置为环境变量
    var_registry_url="http://nexus.xxx.com/repository/apt-hosted/"
    var_registry_userName="admin"
    var_registry_passwd="123"
    
    # 判断传参类型
    if [ -d ${var_input_args} ];then
    var_args_type="dir"
    elif [ -f ${var_input_args} ];then
    var_args_type="file"
    else
    echo "传参有误,请传入路径(eg: ./path/packages|/path/packages)或者文件(eg: aa.deb|/path/aa.deb)"
    exit 1
    fi
    
    ## 函数区
    # 单个文件上传函数,eg: func_single_upload /path/aa.deb
    function func_single_upload(){
    echo "${1} 正在上传中..."
    curl -s -o /dev/null -w "%{http_code}" -v -u "${var_registry_userName}:${var_registry_passwd}" -X POST -H "Content-Type: multipart/form-data" --data-binary "@${1}" ${var_registry_url} > ${var_logs_file} 2>&1
    fvar_status_code=`cat ${var_logs_file} | grep -oE '^[0-9]+$' | awk 'length == 3'`
    if [ $fvar_status_code -eq 200 -o $fvar_status_code -eq 201 ];then
      echo "执行上传 ${1} 成功"
    else
      echo "执行上传 ${1} 失败"
      exit 1
    fi
    }
    
    ## 执行区
    # 根据传参类型进行文件上传操作
    if [ ${var_args_type} == "file" ];then
    func_single_upload ${var_input_args}
    elif [ ${var_args_type} == "dir" ];then
    # 将所有deb文件存到数组
    array_debs=($(find ${var_input_args} -name "*.deb"))
    # 遍历数组进行文件上传
    for i in ${array_debs[@]};do
      func_single_upload ${i}
    done
    else
    echo "参数类型 ${var_args_type} 没有正确定义,请核查"
    exit 1
    fi
    • 在 Debian 上执行脚本
    # 上传文件夹下的所有
    /bin/bash upload_dep.sh ../packages/
    # 上传单个文件
    /bin/bash upload_dep.sh ../packages/expat_2.6.4-1_amd64.deb

    3.9.3.2 从 Hosted 下载包

  • 操作如下(准备debian环境)

    • 添加仓库公钥到本机
    # 备份源列表文件
    cp -ar /etc/apt/sources.list /etc/apt/sources.list.bak
    
    # 公钥获取方式请参考 Hosted 配置章节,将公钥上传到本机
    root@hukanfa:~# ls
    public.gpg.key
    
    # 旧版debian(11及之前版本):将公钥导入本机
    root@hukanfa:~# apt-key add public.gpg.key
    # 新版debian(11及之后版本): 将公钥放到 /etc/apt/trusted.gpg.d/ 目录中
    mv public.gpg.key /etc/apt/trusted.gpg.d/
    • 配置 /etc/apt/sources.list
    # 添加 hosted 仓 注意这个 testing 和 apt-hosted 设置中 Distribution 值一致
    root@hukanfa:~# echo "deb [signed-by=/etc/apt/trusted.gpg.d/public.gpg.key] http://nexus.xxx.com/repository/apt-hosted/ testing main" > /etc/apt/sources.list
    root@hukanfa:~# apt update
    Get:1 http://nexus.xxx.com/repository/apt-hosted testing InRelease [1371 B]
    Get:2 http://nexus.xxx.com/repository/apt-hosted testing/main amd64 Packages [2993 B]
    Fetched 2993 B in 0s (10.3 kB/s)   
    Reading package lists... Done
    Building dependency tree... Done
    Reading state information... Done
    4 packages can be upgraded. Run 'apt list --upgradable' to see them.
    • 拉包测试
    # 使用普通用户拉取包 ,一次下载多个包用空格隔开就行
    hukanfa@hukanfa:~$ apt download expat=2.6.4-1
    获取:1 http://nexus.xxx.com/repository/apt-hosted testing/main amd64 expat amd64 2.6.4-1 [45.9 kB]
    已下载 45.9 kB,耗时 0秒 (223 kB/s)

3.9.4 如何快速下载依赖包

  • 说明

    • 通过前面章节学习,已经知晓如何利用Nexus搭建的apt-hosted仓库去存储离线的deb包
    • 本节主要扩展说明如何批量下载安装依赖包并上传到apt-hosted仓库,使其作为一个真正意义的离线仓库使用
  • 操作如下

    • 示例
    # 官方包网址
    https://ftp.debian.org/debian/pool/main
    https://ftp.up.pt/ubuntu/ubuntu/pool/main
    # 本次需要安装的包如下
    apt-get install -y --no-install-recommends expat=2.6.4-1 libldap-2.5-0=2.5.18+dfsg-3+b1 perl=5.40.0-7 libsqlite3-0=3.46.1-1 zlib1g=1:1.3.dfsg+really1.3.1-1+b1
    • pull_debs.sh拉取上述包及依赖包(包含递归依赖,如A依赖B,B又依赖C等递归)
    #!/bin/bash
    
    ## 变量区
    var_logfile=pull.log
    # 主包名称数组
    array_main_debs=(
      "expat=2.6.4-1"
      "libldap-2.5-0=2.5.18+dfsg-3+b1"
      "perl=5.40.0-7"
      "libsqlite3-0=3.46.1-1"
      "zlib1g=1:1.3.dfsg+really1.3.1-1+b1"
    )
    # 用于跟踪已经安装过的包的关联数组
    declare -A installed_packages
    
    ## 函数区
    # 获取单个包的依赖并安装(递归处理依赖)
    function install_with_depends() {
      local package=$1
      # 如果包已经安装,则跳过
      if [[ -n "${installed_packages[$package]}" ]]; then
          echo "Package $package is already installed, skipping." >> $var_logfile
          return
      fi
      # 标记包为已安装
      installed_packages[$package]=1
      echo "Processing package: $package" >> $var_logfile
      # 获取依赖(这里简化了依赖解析,实际可能需要更复杂的逻辑)
      local depends=$(apt-cache depends $package | grep Depends | cut -d: -f2 | tr -d '<>,' | xargs)
      # 安装包(这里假设 apt install 会处理依赖关系,因此没有递归调用 install_with_depends)
      apt install $package --reinstall -d -y >> $var_logfile 2>&1
      # 如果需要递归处理依赖(不推荐,因为 apt 应该自动处理它们),可以取消下面的注释
      # 但请注意,这可能会导致循环依赖问题或不必要的重复安装
      for dep in $depends; do
        install_with_depends $dep
      done
    }
    
    ## 执行区
    # 遍历主包数组并安装
    for main_deb in "${array_main_debs[@]}"; do
      install_with_depends $main_deb
    done
    • 创建临时目录,将下载的相关依赖包上传到 apt-hosted 仓库
    mkdir tmp01
    cp -ar /var/cache/apt/archives/*.deb ./tmp01
    ./scripts/upload_dep.sh ./tmp01