☰
Nexus制品仓库实战:创建、上传与查看列表全指南
2026/10/15 9:12:52 网站建设 项目流程

1. 从零搭建制品仓库:为什么我最终选了 Nexus

很多团队在项目早期都经历过这样的场景:几个后端服务、几个前端应用,依赖包靠U盘拷、靠聊天工具传,版本一多就彻底乱套。某个公共工具库改了一行代码,谁用了旧版、谁用了新版,全靠口头同步。等到线上出问题回头排查,发现是某台机器上的依赖版本不对,这种坑踩过一次就再也不想踩第二次。

制品仓库就是来解决这个问题的。它本质上是一个专门存放构建产物和依赖包的服务端,把散落在各处的jar包、npm包、Docker镜像、Python wheel统一收拢到一个地方,谁需要谁来取,版本清晰、来源可追溯。而Nexus就是这类工具里最主流的一个,全称是Sonatype Nexus Repository,社区版免费,功能足够中小团队用很久。

这篇文章要聊的就是Nexus最核心的三件事:创建仓库、上传文件、查看列表。听起来简单,但真上手你会发现细节不少——仓库类型选错了后面全白搭,上传方式有好几种各有适用场景,列表查看还涉及搜索和权限。我把自己从零搭建到日常使用的完整过程整理出来,包括踩过的坑和总结的技巧,适合刚接触制品仓库的开发者、需要给团队搭基础设施的运维同学,以及想搞清楚依赖管理到底怎么回事的技术负责人。看完你至少能做到:独立部署一个Nexus、按需创建不同类型的仓库、用合适的方式上传制品、快速定位和查看已有内容。

2. 部署与初始化:把Nexus跑起来

2.1 部署方式的选择与理由

Nexus的部署方式主要有三种:直接跑jar包、用Docker容器、或者装成系统服务。我实测下来最推荐Docker方式,原因很直接——环境隔离干净,升级和迁移都方便,删掉容器重来一遍也就几十秒的事。jar包方式虽然轻量,但依赖宿主机的Java环境,不同机器上Java版本不一致容易出幺蛾子。系统服务方式适合生产环境长期运行,但配置稍繁琐。

用Docker部署的话,一条命令就能起来:

docker run -d \ --name nexus \ -p 8081:8081 \ -v /data/nexus-data:/nexus-data \ --restart unless-stopped \ sonatype/nexus3:latest

这里有几个参数值得说明。-p 8081:8081是默认的Web端口,Nexus的管理界面和仓库服务都走这个端口。-v /data/nexus-data:/nexus-data把数据目录挂载到宿主机,这一步非常关键,否则容器一删你的所有制品就没了。--restart unless-stopped保证宿主机重启后容器自动拉起,省得每次手动启动。

注意:数据目录的权限问题是最常见的启动失败原因。Nexus容器内以UID 200运行,如果挂载的宿主机目录权限不对,容器会起不来或者启动后报错。建议先执行chown -R 200:200 /data/nexus-data再启动。

2.2 首次登录与初始密码获取

容器启动后别急着访问,Nexus初始化需要一点时间,大概一到两分钟。等日志里出现"Started Sonatype Nexus"之类的字样,再打开浏览器访问http://你的服务器IP:8081。

首次登录的用户名是admin,密码不是默认的,而是随机生成后存在数据目录里的一个文件中。获取方式:

docker exec nexus cat /nexus-data/admin.password

拿到这串密码登录进去,系统会强制你修改密码,同时问你是否启用匿名访问。这里有个选择:如果团队内部使用、不对外暴露,可以关闭匿名访问,所有操作都要认证;如果想让CI/CD流水线免认证拉取公开依赖,可以开启匿名访问但只给读权限。我一般建议先关闭匿名,等仓库配置好了再按需开放。

2.3 仓库类型的概念铺垫

在动手创建仓库之前,必须先把Nexus的仓库类型搞清楚,否则后面全是坑。Nexus的仓库分三大类:

  • 代理仓库(Proxy):它自己不存东西,而是当"二传手"。当你请求一个外部公共仓库的包时,Nexus去上游拉取,缓存到本地,下次再有人要就直接给缓存。这样既加速了内网访问,又减少了对上游的依赖。
  • 宿主仓库(Hosted):这是真正存你自己制品的地方。你构建出来的jar包、前端打包产物、内部工具库,都往这里传。
  • 仓库组(Group):它把多个代理仓库和宿主仓库聚合成一个统一入口。开发者只需要配置一个组地址,就能同时访问内部制品和外部依赖,不用记一堆URL。

理解这三者的关系,是后面所有操作的基础。打个比方:代理仓库像是"代购",宿主仓库像是"自家仓库",仓库组像是"前台统一收货窗口"。

3. 创建仓库:三种类型逐一实操

3.1 创建代理仓库(以Maven中央仓库为例)

代理仓库最典型的用途就是代理Maven中央仓库。这样团队里所有人拉取开源依赖都走内网Nexus,速度快且稳定。

操作路径是:登录后点击顶部齿轮图标进入设置,左侧菜单找到Repository,再点Repositories,然后点Create repository。在列表里选择maven2 (proxy)。

关键配置项如下:

配置项建议值说明
Namemaven-central-proxy仓库标识,见名知意
Remote storagehttps://repo1.maven.org/maven2/上游仓库地址
Blob storedefault存储位置,默认即可
Version policyRelease只代理正式版本
Layout policyStrict严格校验路径格式

这里重点说两个参数。Version policy选Release还是Snapshot,取决于你要代理的上游内容。Maven中央仓库只有Release版本,所以选Release。如果你要代理某个包含快照版本的上游,就得单独建一个Snapshot策略的代理仓库。Layout policy选Strict会严格按照Maven的目录规范校验,能避免一些路径混乱的问题,除非有特殊需求否则都选Strict。

还有一个容易被忽略的配置是Negative Cache TTL,默认1440分钟。它的作用是:当某个包在上游不存在时,Nexus会记住这个"不存在"的状态一段时间,避免每次都去上游问一遍。这个值设太小会导致频繁回源,设太大又会导致上游新增了包但你这边迟迟拉不到。1440分钟(一天)是个比较平衡的值。

3.2 创建宿主仓库(存放自己的制品)

宿主仓库是重点,因为你要上传的东西都进这里。同样在Create repository页面,这次选maven2 (hosted)。

配置要点:

  • Name:比如my-releases,用于存放正式版本。
  • Version policy:这里要仔细。如果你这个仓库专门放正式版,选Release;专门放快照版,选Snapshot;两者都放,选Mixed。我强烈建议正式版和快照版分开建两个仓库,因为它们的清理策略和保留周期完全不同,混在一起后期管理会很痛苦。
  • Deployment policy:控制是否允许重复部署。选Allow redeploy可以覆盖同名版本,选Disallow redeploy则同一版本只能传一次。生产环境的正式版仓库建议选Disallow,防止误覆盖;快照仓库选Allow,因为快照本来就是要反复覆盖的。

实操心得:我见过不少团队图省事,正式版和快照版全塞一个Mixed仓库里。结果就是清理策略没法配——你想保留正式版永久、快照只留7天,但Mixed仓库只能配一套规则。最后要么快照堆积如山占满磁盘,要么正式版被误删。分开建,一劳永逸。

3.3 创建仓库组(统一访问入口)

仓库组本身不存东西,它是个逻辑聚合。创建时选maven2 (group),然后把你想聚合的仓库按顺序加进去。

顺序很重要。Nexus会按你排列的顺序依次查找,找到就返回。所以通常把宿主仓库排在前面,代理仓库排在后面。这样请求一个内部包时,先查自家仓库,命中就直接返回;没命中再去代理仓库找外部依赖。如果顺序反了,每次请求内部包都要先去外部仓库空跑一圈,白白浪费时间。

一个典型的组配置顺序是:

  1. my-releases(内部正式版)
  2. my-snapshots(内部快照版)
  3. maven-central-proxy(外部中央仓库代理)

配好之后,开发者只需要在项目的settings.xml或pom.xml里配置这一个组地址,就能同时访问内部和外部所有依赖。

3.4 其他格式仓库的创建思路

除了Maven,Nexus还支持npm、Docker、PyPI、NuGet、Raw等多种格式。创建逻辑大同小异,但有几个格式需要特别注意。

npm仓库:代理仓库指向https://registry.npmjs.org,宿主仓库用来存放内部私有npm包。npm有个特殊之处是它区分npm hosted和npm proxy,配置时别选错。

Docker仓库:Docker仓库的创建稍微复杂,需要配置一个HTTP连接器端口(比如8082),因为Docker客户端不认Nexus的Web端口。创建后还要在Docker客户端配置insecure-registries(如果是HTTP)或者配好证书(如果是HTTPS)。

Raw仓库:这个最灵活,什么格式都能往里扔,适合存放一些非标准格式的构建产物、配置文件、安装包等。没有格式校验,纯当文件服务器用。

4. 上传文件:四种方式按场景选

4.1 界面上传:适合临时和少量

最直观的方式就是通过Web界面。进入某个宿主仓库的Browse页面,会看到一个Upload按钮,点开后可以选文件上传。

这种方式适合临时传一两个文件、验证仓库配置是否正确。但它有明显局限:不能批量、不能自动化、大文件上传容易超时。所以只推荐用来做测试,正式流程别依赖它。

界面上传时有个细节:Maven仓库要求你填GroupId、ArtifactId、Version这些坐标信息,它会根据这些信息自动生成存储路径。如果你填的坐标和实际包的坐标不一致,后面拉取时会找不到。所以填的时候要跟构建产物的真实坐标对齐。

4.2 命令行上传:Maven与Gradle集成

这是最主流的方式,把上传动作集成到构建流程里,构建完自动发布。

Maven方式:在pom.xml里配置distributionManagement:

<distributionManagement> <repository> <id>nexus-releases</id> <url>http://你的Nexus地址:8081/repository/my-releases/</url> </repository> <snapshotRepository> <id>nexus-snapshots</id> <url>http://你的Nexus地址:8081/repository/my-snapshots/</url> </snapshotRepository> </distributionManagement>

然后在settings.xml里配置对应的认证信息:

<servers> <server> <id>nexus-releases</id> <username>admin</username> <password>你的密码</password> </server> <server> <id>nexus-snapshots</id> <username>admin</username> <password>你的密码</password> </server> </servers>

配置好后执行mvn deploy,Maven会根据版本号自动判断往releases还是snapshots仓库传。版本号带-SNAPSHOT的走快照仓库,否则走正式仓库。

Gradle方式:在build.gradle里配置:

publishing { repositories { maven { def releasesRepoUrl = "http://你的Nexus地址:8081/repository/my-releases/" def snapshotsRepoUrl = "http://你的Nexus地址:8081/repository/my-snapshots/" url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl credentials { username = "admin" password = "你的密码" } } } }

Gradle的maven-publish插件配合这段配置,执行gradle publish就能发布。

注意:认证信息千万别硬编码在pom.xml或build.gradle里然后提交到代码仓库。用settings.xml(Maven)或者环境变量、gradle.properties(Gradle)来管理,避免密码泄露。这是安全底线。

4.3 curl命令上传:脚本化和CI场景

有时候你不想引入Maven或Gradle插件,就想用最简单的HTTP请求上传,这时候curl就派上用场了。Nexus的REST API支持直接PUT上传:

curl -v -u admin:密码 --upload-file ./myapp-1.0.0.jar \ "http://你的Nexus地址:8081/repository/my-releases/com/example/myapp/1.0.0/myapp-1.0.0.jar"

这个命令的关键在于URL的构造。Nexus的Maven仓库路径规则是groupId的斜杠形式/artifactId/version/文件名。比如groupId是com.example,artifactId是myapp,version是1.0.0,文件名是myapp-1.0.0.jar,那么路径就是com/example/myapp/1.0.0/myapp-1.0.0.jar。

这个路径必须严格对应,否则虽然文件传上去了,但Maven客户端按坐标找不到它。我踩过一次坑:路径里少写了一层目录,文件确实在仓库里,但mvn dependency:get死活拉不下来,排查了半天才发现是路径不对。

curl方式特别适合CI流水线里用shell脚本发布制品的场景,不依赖任何构建工具的插件。

4.4 批量上传:脚本化处理

当你有几十上百个文件要传时,一个个curl太慢。写个简单的shell脚本循环处理:

#!/bin/bash NEXUS_URL="http://你的Nexus地址:8081/repository/my-releases" USER="admin" PASS="你的密码" upload() { local file=$1 local path=$2 curl -s -u "$USER:$PASS" --upload-file "$file" "$NEXUS_URL/$path" if [ $? -eq 0 ]; then echo "上传成功: $path" else echo "上传失败: $path" fi } # 遍历目录下所有jar包 find ./build/libs -name "*.jar" | while read jar; do filename=$(basename "$jar") # 根据你的项目规则构造路径 upload "$jar" "com/example/$filename" done

批量上传的核心是路径构造规则要统一。建议提前把"文件名到仓库路径"的映射规则定好,写进脚本里,避免手工拼路径出错。

5. 查看列表:搜索、浏览与API

5.1 界面浏览与目录结构

上传完成后,在Web界面点进对应仓库的Browse页面,就能看到树形目录结构。Nexus会按照你上传时的路径自动组织成层级目录,点进去能看到具体文件、大小、上传时间。

这个界面适合快速确认某个包在不在、版本对不对。但如果仓库里东西多了,一层层点效率很低,这时候要用搜索。

5.2 搜索功能的使用技巧

Nexus的搜索框支持按关键字、groupId、artifactId、版本等维度查。几个实用技巧:

  • 用*做通配符,比如搜myapp*能匹配所有以myapp开头的制品。
  • 搜索时可以限定仓库范围,避免在几十个仓库里大海捞针。
  • 搜到的结果可以点进去直接看该制品的所有版本列表,方便对比。

搜索底层走的是Nexus的索引,如果刚上传完搜不到,可能是索引还没更新,等几秒刷新即可。

5.3 REST API查询:自动化场景必备

在脚本或监控系统里查列表,就得用REST API。Nexus提供了丰富的接口:

# 查询某仓库下所有制品 curl -u admin:密码 "http://你的Nexus地址:8081/service/rest/v1/components?repository=my-releases" # 查询特定组件的详细信息 curl -u admin:密码 "http://你的Nexus地址:8081/service/rest/v1/search?repository=my-releases&group=com.example&name=myapp"

返回的是JSON格式,方便用jq等工具解析。比如统计某仓库的制品总数:

curl -s -u admin:密码 "http://你的Nexus地址:8081/service/rest/v1/components?repository=my-releases" | jq '.items | length'

这个能力在写自动化清理脚本、做仓库容量监控时特别有用。

5.4 列表查看的权限控制

列表能看到什么,取决于你的账号权限。Nexus的权限粒度很细,可以控制到"某个仓库的读、写、浏览"级别。

一个常见的需求是:让所有开发者能浏览和拉取,但只有CI账号能上传。实现方式是创建不同的角色(Role),给开发者角色配nx-repository-view-*-*-read和nx-repository-view-*-*-browse权限,给CI账号配nx-repository-view-*-*-add和nx-repository-view-*-*-edit权限,然后把角色分配给对应用户。

实操心得:别图省事所有人都用admin。一旦有人误操作删了制品,你连是谁干的都查不到。Nexus有审计日志,但前提是每个人用自己的账号。权限分离这件事,越早做越好,后期补很麻烦。

6. 常见问题与排查技巧实录

6.1 上传失败排查速查表

现象可能原因排查方向
401 Unauthorized认证信息错误或缺失检查用户名密码、settings.xml配置
403 Forbidden账号无该仓库写权限检查角色权限配置
400 Bad Request路径格式不符合仓库规范检查groupId/artifactId/version路径
404 Not Found仓库名写错或仓库不存在核对仓库Name拼写
上传成功但拉不到路径与坐标不匹配用搜索确认实际存储路径
大文件上传超时默认超时时间太短调整Nexus的请求超时配置

6.2 几个我踩过的坑

坑一:快照版本重复上传后拉取到旧包。快照仓库虽然允许覆盖,但Maven客户端本地有缓存,有时候你传了新快照,客户端还是用旧的。解决办法是拉取时加-U参数强制更新,或者清理本地~/.m2/repository下对应的快照目录。

坑二:代理仓库缓存了错误的包。有次上游仓库某个包发了个有问题的版本,Nexus缓存了。后来上游修复重新发布,但Nexus这边还是给缓存的旧包。这时候需要手动清理该包的缓存,在Browse页面找到对应路径,用"Invalidate cache"功能,或者直接删除缓存目录让它重新拉取。

坑三:磁盘满了导致上传失败。Nexus的blob store会随着制品增多不断膨胀,尤其是代理仓库缓存了大量外部依赖。一定要配置清理策略(Cleanup Policy),定期清理过期的快照和长期未访问的缓存。我一般给快照仓库配"保留最近30天"的策略,代理仓库配"保留最近90天未访问"的策略。

坑四:仓库组顺序配错导致拉取慢。前面提过,组里仓库顺序影响查找效率。有次把代理仓库排在了宿主仓库前面,结果每次拉内部包都要先去外部仓库空跑,整体拉取时间翻倍。调整顺序后恢复正常。

6.3 性能与容量的一些经验值

Nexus对硬件的要求不算高,但有几个经验值可以参考。内存方面,JVM堆建议至少给2GB,制品多的话给4GB。存储方面,代理仓库的缓存增长最快,一个中等规模团队用一年,缓存可能到几十GB。所以数据目录所在的磁盘要留足空间,并且做好监控。

如果团队规模大、并发拉取频繁,可以考虑给Nexus前面加一层反向代理做负载和缓存,但这是进阶话题了,中小团队单实例足够。

7. 我个人的一些使用体会

从第一次搭Nexus到现在,最大的感受是:前期多花半小时把仓库规划好,后期能省几十小时的排查时间。仓库命名要规范、正式版和快照版要分开、权限要按角色分配、清理策略要提前配——这四件事做到了,日常使用基本不会出问题。

另一个体会是,上传方式的选择要跟着场景走。临时验证用界面,正式发布用Maven/Gradle插件,CI脚本用curl,批量处理写循环脚本。别用一种方式硬套所有场景,那样要么效率低,要么容易出错。

最后分享一个小技巧:给每个仓库配一个描述(Description),写清楚这个仓库是干什么的、谁负责维护、清理策略是什么。过几个月回头看,你会感谢当时写描述的自己的。团队里新人进来,看一眼描述就知道该往哪个仓库传东西,省去大量沟通成本。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询