
如果你维护过一条稍微正式的软件交付链路大概率遇到过这些场面开发本地反复下载依赖包网速随带宽心情波动构建机上传产物没有固定位置同一个 jar 包散落在好几台服务器线上要回滚到上一个稳定版本却谁都说不清当初的包到底扔在哪儿。这些问题凑到一起基本就是在提醒你该上一个二进制制品仓库了。而我今天要聊的 Nexus就是这个领域最常用、也最值得优先考虑的方案之一。这里先做个澄清避免搜错东西。网上搜“nexus”会出现两个完全不同的产物一个是桌面美化工具 Winstep Nexus悬浮图标、Dock 栏美化用的跟代码仓库没有半点关系另一个就是本文要讲的 Sonatype Nexus Repository Manager企业级二进制制品仓库管理平台。如果你是想解决依赖管理和制品分发的问题看这篇就对了。正文会从实际场景出发覆盖 Nexus 的核心概念、安装部署、仓库创建、与 Maven/npm/Docker 的集成、权限安全、备份与常见故障排查。内容偏向实操命令和配置都以 3.x 版本为例适合刚接触 Nexus 的运维、DevOps 工程师也适合团队里想统一构建产物管理的开发同学。1. 为什么企业需要一个二进制制品仓库1.1 没有统一管理平台时的典型混乱现场先回想一下你的项目依赖是从哪里来的大多数早期团队是全员直连公共源比如 Maven 的中央仓库、npm 官方源、Python 的 PyPI。问题在团队小、项目少的时候不明显等团队上了规模痛点就开始集中爆发。一是网络问题。开发环境访问公共源时快时慢同一个依赖包十个人可能下载了十遍构建服务器每次跑流水线也要重复下载既浪费时间也消耗出口带宽。如果团队在某些网络受限的环境里开发直接拉公共源甚至可能失败。二是制品归属混乱。自己开发的公共模块被打成 jar、镜像、npm 包之后没有一个明确的归属地。有人传到内网共享盘有人挂到某台服务器目录有人干脆塞在自己的电脑里。后续部署要用只能群里到处问找回来的包对不对、是否经过审核完全没有概念。三是安全和审计缺失。公共源里出现过不少恶意组件被投毒的案例没有一层缓存和校验机制开发人员会直接把这些不确定的依赖拉进项目。同时团队内部产物的发布记录、下载记录也完全不可控出问题后没法追踪。1.2 Nexus 到底解决了什么问题Nexus 这类二进制制品仓库的核心作用可以概括成三件事代理、托管、聚合。代理指的是它对公共源做缓存开发第一次从公共源拉取依赖时Nexus 会帮你下载并存在本地后续所有人再从 Nexus 拉取速度就是内网速度哪怕断外网也不影响已缓存组件的使用。托管指的是你自研的构建产物可以集中发布到 Nexus 里形成私有仓库团队内部共享。聚合则是通过仓库组Repository Group把多个代理仓库和托管仓库合成一个统一的访问入口开发人员只配一个地址就能同时获取公共依赖和私有组件。简单概括Nexus 就是给二进制制品提供了一个类似 Git 的集中式管理底座。代码有 Git 管理构建产物同样需要一套体系和规范不然交付链路就是一团散沙。2. 核心概念与版本选型2.1 三个仓库模型Proxy、Hosted、Group这里必须先理解 Nexus 最核心的三个仓库类型后面所有的配置都是围绕它们展开的。Proxy 是代理仓库。它的作用是连接外部公共源比如 Maven Central、npm 官方源、Docker Hub、PyPI通过配置远程仓库地址和访问策略Nexus 把外部组件缓存到本地。开发者的请求不再直接打到公网而是走 Nexus 这一层。你可以给每个格式建对应的 proxy 仓库也可以指定缓存保留策略和组件保留策略。Hosted 是托管仓库。这是用来存放企业内部自有组件的地方。比如团队自己开发的公共库、打好的安装包、定制化镜像都可以发布到这里。它相当于公司的私有仓库归你全权管理。为了更好地控制你可以把 hosted 仓库设为 online 或 offline也能通过权限配置限制谁能发布、谁能读取。Group 是仓库组。它像一个大聚合入口把多个 proxy、hosted 仓库组合在一起对外只暴露一个地址调用。这样做的最大好处是简化客户端配置开发人员不需要知道底层有几个仓库只要访问统一地址就行Nexus 会按照仓库组的顺序去寻找组件。这三个类型是使用 Nexus 的基石。实际规划时我习惯于针对每类技术栈建一套“proxy hosted group”的组合比如 Maven 就是 maven-public、maven-central、maven-releases、maven-snapshots 这样的命名结构。2.2 Nexus 2 与 Nexus 3 怎么选很多人搜索时会看到docker nexus 2这样的关键词这里也顺便说明一下。Nexus 2 是老一代产品配置界面和仓库模型跟 3 差异很大而且已经停止功能开发只保留安全维护。现在新部署项目再用 2 属于自找麻烦。Nexus 3 是当前主推版本在底层架构、性能、支持的仓库格式上都做了大量提升。它内置了比 2 更完善的权限模型支持 Docker Registry、npm、PyPI、Go、raw 等更多格式界面也更加现代化。如果你是从零开始直接用 Nexus 3 新版本不用犹豫。2.3 资源占用与功能对比的选型参考我们拿同样流行的 JFrog Artifactory 做个简单对比方便你评估选型。对比维度Nexus 3JFrog Artifactory许可证OSS 版本免费商业版收费为主安装复杂度低单 Java 应用相对较重资源占用内存 2G 起可跑多服务方案更耗资源支持的格式Maven、npm、Docker、PyPI、raw 等类似格式覆盖广企业功能权限、LDAP、 cleanup、REST API更精细的元数据与策略最适合场景中小团队、成本敏感大规模、跨团队复杂治理我在实际项目里选型的关键判断是团队有没有强合规和复杂权限治理需求。没有的话Nexus 免费版已经能覆盖绝大多数日常场景运维成本也更低。3. 安装部署实录从零开始跑起 Nexus3.1 环境准备与安装方式选择Nexus 是个 Java 服务所以最核心的前置依赖是 JDK。需要注意不同版本的 Nexus 对 JDK 版本要求不一样。以 Nexus 3.70 之后的版本为例官方要求必须 JDK 17还在用 JDK 8 的老环境建议装回 Nexus 3.60 之前的老版本或者是直接升级 JDK不建议强行跑在旧环境上。官方提供三种常见安装方式压缩包安装、Docker 容器运行、RPM 包安装。其中压缩包安装最通用适合 Linux 服务器Docker 运行最适合快速验证RPM 包在 RedHat/CentOS 系环境里也方便。我们这里以压缩包安装为主同时附上 Docker 方式作为备选。安装前建议准备一台至少 2 核 4G 内存的服务器磁盘则根据制品增长情况预估一般建议预留 200G 以上。Nexus 默认把构建数据和临时文件放在 sonatype-work 目录这个目录所在分区必须确保有足够的剩余空间。3.2 压缩包安装与初始化配置先用官网或者国内镜像下载 Nexus 的 unix 压缩包。我这里以 nexus-3.70.0-04 为例下载完成后解压到 /opt/nexus 目录。为了安全我不会使用 root 账号直接运行服务而是创建一个专门的 nexus 用户。mkdir -p /opt/nexus tar -zxvf nexus-3.70.0-04-unix.tar.gz -C /opt/nexus ln -s /opt/nexus/nexus-3.70.0-04 /opt/nexus/nexus-current useradd -r -m -d /home/nexus -s /bin/bash nexus chown -R nexus:nexus /opt/nexusNexus 安装包里有几个目录需要清楚nexus-current 是程序目录里面是 bin、lib、conf启动后自动生成的 sonatype-work 是数据目录。数据目录里存储了所有仓库配置、已缓存组件、用户信息和审计日志备份时重点看它。首次启动时可以用前台模式验证是否能正常起服务。sudo -u nexus /opt/nexus/nexus-current/bin/nexus run看到类似Started Sonatype Nexus OSS的日志就说明启动成功。确认没问题后按下 CtrlC 停掉然后改成后台启动模式sudo -u nexus /opt/nexus/nexus-current/bin/nexus start启动后默认访问端口是 8081。浏览器访问http://服务器IP:8081/如果不能打开先检查防火墙和云平台安全组是否放行 8081 端口。另外确认一下进程是否真的起来了有时候 Nexus 启动很慢第一次可能要等两三分钟别急着判断失败。3.3 用 systemd 管理 Nexus 服务后台启动方式虽然简单但重启服务器后不会自动拉起。生产环境我给团队推荐用 systemd 实现服务化管理。在 /etc/systemd/system/nexus.service 创建服务配置[Unit] DescriptionSonatype Nexus Repository Manager Afternetwork.target [Service] Typeforking Usernexus Groupnexus ExecStart/opt/nexus/nexus-current/bin/nexus start ExecStop/opt/nexus/nexus-current/bin/nexus stop Restarton-abort LimitNOFILE65536 [Install] WantedBymulti-user.target配置完成后执行 systemctl daemon-reload然后就能通过 systemctl start/stop/status nexus 来管理服务了。注意 LimitNOFILE 一定要设置Nexus 需要大量文件描述符默认的 1024 上限会在高负载时诱发奇怪问题。3.4 Docker 方式部署要点如果只是测试或者容器环境部署官方镜像 sonatype/nexus3 很方便mkdir -p /data/nexus chown -R 200:200 /data/nexus docker run -d --name nexus \ -p 8081:8081 \ -v /data/nexus:/nexus-data \ sonatype/nexus3这里有一个很容易踩的坑Nexus 容器内进程默认以 uid 200 运行挂载目录属主必须改成 200不然容器启动后会报目录权限不足数据也无法写入。我见过不少人直接 -v 挂载到宿主机新目录结果容器反复重启才反应过来是属主问题。4. 仓库创建实操Maven、npm、Docker 一个都不能少4.1 先创建 Blob StoreNexus 的存储层概念叫 Blob Store可以理解为实际保存二进制内容的空间。默认安装后有一个叫 default 的 Blob Store所有仓库共用。这种做法在制品量不大时没问题但一旦某个仓库异常膨胀或者你想把不同团队的存储分到不同磁盘就会相当被动。我的习惯是每类仓库建独立 Blob Store比如 blob-maven、blob-npm、blob-docker。操作路径是 Settings 菜单里的 Repository - Blob Stores点击 Create Blob Store类型选 File填写名称并指定存储路径。路径留空则使用默认 sonatype-work 下的目录。4.2 创建 Maven 仓库组接下来以 Maven 为例演示一套完整的 proxy hosted group 结构。进入 Settings - Repository - Repositories点击 Create Repository选择 maven2(proxy) 类型。首先是 maven-central远程地址填https://repo1.maven.org/maven2/Blob Store 选之前建的 blob-maven其他选项保持默认。这样 Nexus 就能代理 Maven Central 并缓存所有拉取的组件。然后是 maven-releases选择 maven2(hosted) 类型。这里有一个关键选择Version Policy 选 Release代表只允许发布发布版本再建一个 maven-snapshotsVersion Policy 选 Snapshot专门存放快照版本。这种区分是 Maven 社区一直以来的规范release 和 snapshot 版本混在一个仓库里会造成不少混乱。最后创建 maven-public选择 maven2(group) 类型把 maven-central、maven-releases、maven-snapshots 都加进仓库组。最终对外只暴露 maven-public 一个地址。4.3 创建 npm 私有源npm 仓库的创建流程和 Maven 类似。先建 npm(proxy) 仓库远程地址写https://registry.npmjs.org/缓存策略选 Default。再建 npm(hosted) 仓库作为内网私有包仓库。最后建一个 npm(group) 仓库包含以上两个。npm 有一点和 Maven 不同Nexus 对 npm hosted 仓库的认证要求更严格发布私有包必须通过带认证的账号执行 npm login。这个后续接入部分会讲具体命令。4.4 创建 Docker 镜像仓库Docker 仓库在 Nexus 里有点特殊它不是一个统一访问入口而是每个 Docker 仓库都有独立的端口。原因很简单Docker 客户端与 registry 的通信直接基于 HTTP 协议需要通过不同端口区分不同仓库。创建 Docker(hosted) 仓库时勾选 HTTP设置端口为 8082创建 Docker(proxy) 仓库时远程地址填https://registry-1.docker.io设置端口为 8083并在 Docker Index 选项里选择 Use Docker Hub。如果内外网都要用再建一个 Docker(group) 仓库选 HTTP 端口 8084把 hosted 和 proxy 都加进去。这里的核心操作意图是给每个仓库分配独立端口这样 docker pull 的时候可以用IP:端口/镜像名来区分是私有镜像还是代理缓存镜像。Nexus 全局设置的 Docker 仓库统一入口和组策略也有关系但按端口访问是最直观的做法。5. 与构建工具衔接让开发真正用起来5.1 Maven 项目接入仓库建好之后开发人员需要修改 Maven 的 settings.xml 才能让项目从 Nexus 拉取依赖。通常在 Maven 安装目录的 conf/settings.xml 或者用户目录下的 ~/.m2/settings.xml 中配置。首先是镜像配置让所有依赖请求都走 Nexusmirrors mirror idnexus/id mirrorOf*/mirrorOf nameNexus Repository Manager/name urlhttp://192.168.56.10:8081/repository/maven-public//url /mirror /mirrors这里 mirrorOf 设置为 *表示所有中央仓库、公共仓库的请求都会被拦截并转向到 Nexus 的 maven-public 组。这样做的好处是开发人员不需要知道任何公共源地址也保证依赖包全部经过缓存层。如果你想发布公司内部模块到 hosted 仓库还需要配置 distributionManagement 和 server 认证servers server idnexus-releases/id usernamedeployment/username password你的密码/password /server /servers然后在具体 pom.xml 里加distributionManagement repository idnexus-releases/id urlhttp://192.168.56.10:8081/repository/maven-releases//url /repository snapshotRepository idnexus-snapshots/id urlhttp://192.168.56.10:8081/repository/maven-snapshots//url /snapshotRepository /distributionManagement注意 server 的 id 必须和 distributionManagement 里的 id 保持一致不然 Maven 找不到凭证发布时会报 401。5.2 npm 与 pip 接入npm 的接入更加直接。开发人员只需要在项目中配置 registry 地址npm config set registry http://192.168.56.10:8081/repository/npm-public/如果是首次使用私有 hosted 仓库需要先登录npm login --registryhttp://192.168.56.10:8081/repository/npm-hosted/登录时会要求输入用户名密码建议在 Nexus 里单独创建一个 ci 账号给发布流程使用不要把 admin 账号暴露给所有开发人员。发布私有包时执行 npm publishNexus 会自动接收并存储到 npm-hosted 仓库中。Python 项目则可以通过 pip 配置。创建一个 pypi(proxy) 仓库指向https://pypi.org/simple/一个 pypi(hosted) 仓库用来发布内部包开发人员在 pip.conf 中配置 index-url 指向 npms... 指向 Nexus 的 pypi 仓库组即可。这里就不展开命令了思路完全相同。5.3 Docker 客户端登录配置Docker 客户端的配置比 Helm、npm 麻烦一点点核心是解决镜像仓库的 SSL 信任问题。因为 Nexus 如果以 HTTP 方式暴露 Docker 仓库Docker 默认会把 HTTP 仓库当成不安全 registry必须显式声明。修改 /etc/docker/daemon.json{ insecure-registries: [192.168.56.10:8082, 192.168.56.10:8083] }改完重启 Dockersystemctl restart docker然后就可以用标准命令登录和推拉了docker login 192.168.56.10:8082 docker tag my-app:latest 192.168.56.10:8082/my-app:latest docker push 192.168.56.10:8082/my-app:latest这里特别提醒insecure-registries 里的地址要和登录地址保持完全一致包括端口。很多人配了之后登录报证书错误或者 connection refused基本都是地址没对齐或者端口不小心填成了 8081。6. 权限、安全与日常运维6.1 用户角色与匿名访问默认安装后 admin 账号是个特殊存在。Nexus 3 首次启动时会在数据目录生成一个随机初始密码文件路径是sonatype-work/nexus3/admin.password用文本编辑器打开就能看到。第一次登录后系统会强制你修改密码之后这个文件会被删除。随后建议立刻创建一套最小化权限体系。千万不要让所有人都用 admin。在设置菜单的 Security - Users 里创建用户建议至少分两类开发用户只拥有读取、浏览仓库的权限发布用户额外拥有对 hosted 仓库的编辑、上传权限。Nexus 权限模型由用户、角色、权限三层组成可以在 Roles 页面自定义角色在 Privileges 页面勾选对应仓库的访问、读取、创建、更新权限。如果你想让开发人员在没有账号的情况下也能拉取公共依赖可以允许匿名访问。设置菜单的 Security - Anonymous Access 里打开开关。但如果有内网敏感制品匿名访问等于给所有人开了后门这种场景下务必关闭匿名访问改为必须认证后拉取。6.2 HTTPS 与反向代理一般生产环境里Nexus 前面最好再挂一层 Nginx承担 HTTPS 终止和访问控制。这样好处是证书管理集中对 Nexus 本身的资源配置压力也小。Nginx 反向代理配置核心点是把 / 路径转发到 8081如果需要 Docker 仓库Nginx 还需要额外开启 stream 端口转发处理起来略复杂。这里给一个最基础的 HTTP 反向代理配置server { listen 80; server_name nexus.example.com; client_max_body_size 0; location / { proxy_pass http://127.0.0.1:8081/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }配置完成后开发人员访问http://nexus.example.com/repository/maven-public/就能替代原来的 IP 访问方式。如果后续上了 HTTPS再在配置里补上证书文件即可。6.3 备份恢复与磁盘告警备份是运维 Nexus 最重要的工作没有之一。Nexus 的数据包括三个部分仓库配置、用户权限配置、Blob 里的制品内容。最简单的可靠备份方式是停止服务后直接拷贝整个 sonatype-work 目录但这种冷备方式在生产环境不现实。实际中更推荐做两件事一是定期执行 Nexus 自带的备份功能在 System - Backup 页面手动触发一次配置备份二是用文件系统层快照对 sonatype-work 下的 blob 存储目录做定时快照。Linux 下可以用 LVM 快照或者直接用定时 tar 打包关键目录需要注意文件量大时打包很耗时。恢复时有一个容易忽略的点Nexus 版本必须和备份时的版本完全一致跨版本恢复配置数据很容易出现数据库结构不兼容的问题。所以升级前一定要先备份并且把版本信息记录下来。磁盘容量的监控也不能忘。Nexus 缓存组件和托管组件都会占用大量磁盘建议对 sonatype-work 所在分区设置一个磁盘使用率告警比如超过 80% 就通知运维。在 System - Cleanup Policies 里可以设置清理策略例如删除超过 90 天未访问的 Maven 快照版本或者限制每个仓库保留镜像版本数量。7. 常见问题排查与避坑清单7.1 启动失败与端口冲突Nexus 启动失败最常见的三大原因是 Java 版本不对、端口被占用、数据目录权限错误。Java 版本不对的报错通常是一堆类加载异常或 UnsupportedClassVersionError解决办法是检查java -version确认满足当前 Nexus 版本要求的 JDK 版本并确保系统默认 java 指向正确。端口被占用相对容易判断执行ss -lntp | grep 8081看到已有进程监听就说明冲突了。这时要么杀掉占用进程要么修改 nexus 配置文件里的 application-port。数据目录权限错误多见于手工解压以后用 root 跑过一次之后切到普通用户起服务就报权限拒绝解决方式是执行chown -R nexus:nexus /opt/nexus之后统一用 systemd 管理。7.2 仓库拉取超时与身份认证异常拉取第三方依赖超时一般先看代理仓库的远程地址是不是能通。这里教一个很实用的排查思路直接在浏览器里访问 Nexus 的仓库目录界面比如http://IP:8081/repository/maven-public/junit/如果能打开说明仓库访问没问题再往下排查 maven 配置如果页面都打不开去看 Nexus 服务日志通常会记录远程仓库连接失败的原因。身份认证异常则比较容易定位。开发反馈发布时报 401要么是账号密码错误要么是该账号没有对应仓库的上传权限。在 Security 里检查用户角色的权限范围。一个常见坑是给用户分配了错误的仓库权限比如只有 maven-public 的读权限却想上传到 maven-releases这种情况永远成功不了。7.3 磁盘膨胀与性能相关的问题Nexus 跑久了磁盘占用会持续增长尤其快照版本和 Docker 镜像。我的习惯是定期在 Cleanup Policies 里设置清理任务例如 maven-snapshots 里的快照保留最近 30 天maven-releases 里的历史版本保留最近 10 个。Docker 镜像则建议限制保留最近 N 个 tag避免每次构建生成新镜像把所有旧版本全堆积在磁盘上。性能方面常见问题是内存不足。Nexus 默认 JVM 最大堆可能只有 2G 左右如果单日制品访问量很大可以调整安装目录下 bin/nexus.vmoptions 里的 -Xmx 参数。但是要注意堆内存不要盲目调大最好结合系统物理内存和实际压测情况设定同时关注垃圾回收日志。调完参数后需要重启 Nexus 生效。7.4 常见问题速查表现象可能原因处理方式首次访问页面 503/502Nexus 尚未完全启动等待 2-3 分钟或查看日志确认登录提示密码错误用了初始密码文件删除后的旧密码重置 admin 密码或检查 password 文件Maven 拉取不到公共依赖mirrorOf 配置遗漏或代理远程不通检查 settings.xml测试代理仓库地址Docker 登录报 x509 证书错误HTTP 仓库未加入 insecure-registries修改 daemon.json 并重启 Docker上传制品后页面看不到用户缺少浏览权限或索引未更新检查权限执行 Repository 的 Rebuild Index磁盘空间持续告警快照和镜像保留策略缺失增加 Cleanup Policies定期清理我觉得排查问题核心还是先看日志。Nexus 日志文件在 sonatype-work/nexus3/log 目录下常见的有 nexus.log、request.log 和 access.log。遇到任何疑难杂症先 tail 看日志里的异常堆栈八成能定位出方向远比盲目改配置有用。写在最后的几点实测体会Nexus 这块我用下来的最大感受是工具本身并不复杂真正需要花心思的是仓库规划和权限设计。刚开始图省事把仓库组和用户角色全堆在一起开发、测试、线上混用一个月后想清理都不知道从哪下手。后来老老实实按格式、按用途、按环境分类虽然前期配置多花半天但后面的日常运维基本不用操心。还有一个容易被忽视的小细节团队里约定统一的制品命名和版本规范比搭建仓库本身更重要。仓库搭建只是手段让所有人知道哪个包该发到哪个仓库、版本号如何递增才是二进制制品管理真正落地的前提。如果你们团队还在早期我建议别一上来就上特别复杂的权限模型和策略。先把 Maven 或 npm 的 proxy hosted group 结构搭好让开发从 Nexus 拉依赖、往 Nexus 发制品跑通一条完整链路再加权限和清理策略。一步步来比什么都强。