1. 为什么需要 Jenkins 与 Nexus 的联动在软件开发的持续集成与持续交付CI/CD流水线中构建产物Artifact的管理是一个核心但常被忽视的环节。很多团队在 Jenkins 上跑通了自动化构建和测试但最终生成的 Jar、War、Docker 镜像等文件往往被随意地丢在 Jenkins 工作空间或某个共享目录里。这种做法会带来一系列问题你无法追溯某个测试环境部署的到底是哪个版本的包回滚时找不到历史版本多分支并行开发时构建产物相互覆盖更别提在微服务架构下成百上千个组件版本的管理了。这时一个专门的制品库Artifact Repository就显得至关重要。Nexus Repository Manager通常简称 Nexus是这类工具中的佼佼者它就像一个专为软件包设计的“图书馆”或“仓库管理员”。而 Jenkins 作为自动化构建的“工人”需要将生产出的“产品”软件包规范地存放到这个图书馆里并记录下准确的“入库单”元数据。Jenkins 的 Nexus Platform Plugin 正是连接这位“工人”和“图书馆管理员”的桥梁。它让 Jenkins 在构建结束后能够自动、可靠地将构建产物发布到 Nexus 指定的仓库中并为这次发布打上构建编号、Git Commit ID 等标签。这样一来从代码提交到生成可部署制品的整个链路就完全自动化且可追溯了。今天我就结合自己多次搭建和配置的经验手把手带你走通从插件安装、配置到实战上传的完整流程并分享几个容易踩坑的细节。2. 环境准备与插件安装奠定坚实基础在开始配置插件之前确保你的基础环境是就绪的。这就像盖房子前先打好地基忽略这一步后面的所有操作都可能摇摇欲坠。2.1 基础环境检查清单首先确认以下服务已正常部署并互通Jenkins 实例版本建议在 2.346.x 以上长期支持版。确保你能以管理员或具有全局配置权限的账号登录。Nexus Repository Manager 3版本建议 3.68.x 以上。你需要知道它的访问地址例如http://nexus.your-company.com:8081以及管理员账号密码。网络连通性从 Jenkins 服务器所在的网络必须能够访问 Nexus 服务器的地址和端口默认8081。你可以通过在 Jenkins 服务器上执行curl -I http://nexus.your-company.com:8081来简单测试。构建项目准备准备一个简单的 Maven 或 Gradle 项目作为测试用例。一个最简单的 Spring Boot 项目就非常合适。2.2 安装 Nexus Platform Plugin插件的安装过程在 Jenkins 中比较标准化但有些细节值得注意。登录你的 Jenkins 管理后台依次点击系统管理 - 插件管理 - 可选插件。 在右上角的搜索框中输入 “Nexus Platform”。你会看到由 Sonatype 官方发布的Nexus Platform Plugin。这个插件是一个聚合插件它包含了用于 Jenkins Pipeline 的步骤nexusArtifactUploader以及用于 Freestyle 项目的后置构建操作。注意市场上可能有名称类似的旧插件或第三方插件请务必认准 “Nexus Platform Plugin” 和发布者 “Sonatype”。安装官方插件能获得最好的兼容性和支持。勾选该插件然后点击页面底部的立即下载并在重启后安装。安装完成后按照提示重启 Jenkins 服务。重启后这个插件的能力就已经注入到你的 Jenkins 中了。你可以在流水线语法查询器Pipeline Syntax里看到新增的nexusArtifactUploader步骤或者在 Freestyle 项目的“构建后操作”里找到“Upload artifacts to Nexus Repository Manager”的选项。3. 在 Jenkins 中配置 Nexus 服务器连接信息插件安装好后我们需要告诉 Jenkins 你的 Nexus 服务器在哪里以及用什么身份去访问。这一步是在 Jenkins 的系统配置层面完成的一次配置所有项目都能使用。进入系统管理 - 系统配置滚动页面你会找到名为Nexus的区域。添加 Nexus 实例点击“Add Nexus Instance”。配置实例参数ID 这是一个内部标识符可以自定义如my-company-nexus。在 Pipeline 脚本中会用到这个 ID。Display Name 显示名称例如 “公司内部 Nexus 3”。Server URL 你的 Nexus 服务器根地址如http://nexus.your-company.com:8081。务必确保这是 Nexus 的 Web UI 访问地址而不是 Docker 私有仓库的地址默认8082端口。Credentials 这是最关键的一步。点击“Add”添加一个 Jenkins 凭证。类型选择“Username with password”。在 Nexus 中你需要创建一个专门用于 Jenkins 集成的账号强烈建议不要直接使用 admin 账号。例如创建一个名为jenkins-deploy的用户并赋予它相应仓库的“读写”权限例如对maven-releases和maven-snapshots仓库的nx-repository-view-*-*-*权限。将用户名和密码填入凭证。Test Connection 填写完 URL 和选择凭证后务必点击这个按钮。如果配置正确你会看到绿色的“Successfully connected to Nexus instance ‘xxx’”提示。如果失败请检查网络、URL 和凭证权限。实操心得凭证的权限管理是安全的关键。我习惯为 Jenkins 创建专属用户并遵循最小权限原则。例如如果这个流水线只负责发布 Release 包就只给它maven-releases仓库的写入权限和maven-releases、maven-public的读取权限。这能有效降低误操作或凭证泄露带来的风险。配置完成后保存系统配置。至此Jenkins 全局层面已经知道了如何与你的 Nexus 对话。4. 为 Maven 项目配置构建后上传我们以最常见的 Freestyle 类型 Maven 项目为例演示如何配置构建后自动上传制品。假设你已有一个配置了 Maven 构建步骤的 Jenkins 任务。4.1 配置构建后操作在 Jenkins 任务配置页面找到构建后操作区域点击“增加构建后操作步骤”在下拉列表中选择Upload artifacts to Nexus Repository Manager。这个界面需要你填写一系列关于“上传什么”和“上传到哪里”的信息。Nexus Instance 选择你在系统配置中创建的 Nexus 实例如 “公司内部 Nexus 3”。Nexus Repository 输入目标仓库的 ID。这个 ID 是你在 Nexus 中创建的仓库名称例如maven-releases用于稳定版或maven-snapshots用于快照版。注意这里填的是仓库 ID不是仓库的显示名称。Protocol 选择maven2对于 Maven 项目。Group Id、Artifact Id、Version、Packaging 这些字段通常可以留空插件会自动从项目的pom.xml文件中解析。但如果你有特殊需求比如上传一个非标准 Maven 构建的包也可以手动指定。Classifier 分类器例如sources、javadoc非必填。Extension 扩展名如jar、war通常会自动识别。最关键的部分在Artifacts区域。这里你需要指定要上传哪些文件。4.2 指定上传的制品文件点击“Advanced”展开高级选项在Artifacts输入框里你需要使用groupId:artifactId:version:packaging:classifier:file的格式来定义。对于标准 Maven 构建一个最常用的模式是**/*.jar但这可能过于宽泛。更精确的配置是结合你的项目实际产出。例如你的项目生成了主 Jar 包、源码包和文档包可以这样配置每行一个**/*.jar:${POM_GROUPID}:${POM_ARTIFACTID}:${POM_VERSION}:${POM_PACKAGING}::${WORKSPACE}/target/*.jar **/*-sources.jar:${POM_GROUPID}:${POM_ARTIFACTID}:${POM_VERSION}:${POM_PACKAGING}:sources:${WORKSPACE}/target/*-sources.jar **/*-javadoc.jar:${POM_GROUPID}:${POM_ARTIFACTID}:${POM_VERSION}:${POM_PACKAGING}:javadoc:${WORKSPACE}/target/*-javadoc.jar这里用到了 Jenkins 的内置环境变量如${WORKSPACE}和 Maven 属性变量如${POM_GROUPID}它们会在构建时被动态替换。这种写法虽然稍复杂但非常清晰和准确。提示你可以利用 Jenkins 构建后的“归档制品”步骤先看看target/目录下具体生成了哪些文件再据此编写精确的匹配模式避免上传不必要的文件。配置完成后保存任务。下次构建成功时Jenkins 就会自动将指定的制品上传到你配置的 Nexus 仓库中。你可以在 Nexus 的 Browse 界面中查看上传的组件。5. 在 Pipeline 中使用 nexusArtifactUploader 步骤对于更现代、更灵活的 Jenkins Pipeline声明式或脚本式我们使用nexusArtifactUploader步骤来实现上传功能。这种方式将配置写在Jenkinsfile中与代码一起进行版本控制是更推荐的做法。5.1 编写基本的 Pipeline 脚本以下是一个声明式 Pipeline 的示例它在 Maven 构建成功后上传主 Jar 包和源码包到 Nexus 的 Snapshot 仓库。pipeline { agent any tools { maven Maven-3.9.6 // 假设你在 Jenkins 全局工具配置中配置了这个 Maven 版本 } stages { stage(Checkout) { steps { git branch: main, url: https://your-git-repo.com/your-project.git } } stage(Build) { steps { sh mvn clean package -DskipTests } } stage(Upload to Nexus) { steps { nexusArtifactUploader( nexusInstanceId: my-company-nexus, // 与系统配置中的 ID 一致 nexusRepository: maven-snapshots, // 目标仓库 ID protocol: maven2, groupId: com.yourcompany, // 可以动态获取见下文 version: 1.0-SNAPSHOT, // 可以动态获取见下文 artifacts: [ [artifactId: your-artifact-id, classifier: , file: target/your-artifact-id-1.0-SNAPSHOT.jar, type: jar], [artifactId: your-artifact-id, classifier: sources, file: target/your-artifact-id-1.0-SNAPSHOT-sources.jar, type: jar] ] ) } } } }5.2 动态获取 Maven 项目坐标信息上面的例子中groupId、artifactId、version是硬编码的这不利于复用。更好的做法是从pom.xml中动态读取。我们可以使用readMavenPom步骤需要 Pipeline Utility Steps 插件来达成。stage(Upload to Nexus) { steps { script { def pom readMavenPom file: pom.xml nexusArtifactUploader( nexusInstanceId: my-company-nexus, nexusRepository: maven-snapshots, protocol: maven2, groupId: pom.groupId, version: pom.version, artifacts: [ [artifactId: pom.artifactId, classifier: , file: target/${pom.artifactId}-${pom.version}.jar, type: pom.packaging], [artifactId: pom.artifactId, classifier: sources, file: target/${pom.artifactId}-${pom.version}-sources.jar, type: jar] ] ) } } }这样无论pom.xml里的坐标如何变化你的 Pipeline 都能自动适应。6. 高级配置与常见问题排查在实际使用中你可能会遇到一些复杂场景或错误。下面分享几个进阶配置和排坑经验。6.1 根据分支自动选择仓库一个常见的需求是main分支的构建产物上传到maven-releases仓库而develop或功能分支的构建产物上传到maven-snapshots仓库。这可以在 Pipeline 中通过判断分支名来实现。stage(Upload to Nexus) { steps { script { def pom readMavenPom file: pom.xml def targetRepository maven-snapshots // 默认快照仓库 if (env.BRANCH_NAME main || env.BRANCH_NAME master) { // 确保版本号不是快照版本否则 Nexus 会拒绝上传到 Release 仓库 if (!pom.version.endsWith(-SNAPSHOT)) { targetRepository maven-releases } else { error(主分支的版本号不能是 SNAPSHOT: ${pom.version}) } } nexusArtifactUploader( nexusInstanceId: my-company-nexus, nexusRepository: targetRepository, protocol: maven2, groupId: pom.groupId, version: pom.version, artifacts: [ // ... artifacts 定义 ] ) } } }6.2 处理认证失败与网络问题最常见的错误是401 Unauthorized或403 Forbidden。检查凭证首先确认在 Jenkins 系统配置中为 Nexus 实例选择的凭证是正确的并且该 Nexus 用户密码未过期。检查权限登录 Nexus检查该 Jenkins 用户是否对目标仓库拥有nx-repository-view-*-*-add和nx-repository-view-*-*-edit权限即写入权限。检查 URL确认 Server URL 没有多余的斜杠或使用了错误的端口。另一个常见错误是连接超时或拒绝连接。网络诊断在 Jenkins 服务器上使用telnet nexus-host 8081或curl -v http://nexus-host:8081测试基础连通性。防火墙与代理检查 Jenkins 服务器和 Nexus 服务器之间的防火墙规则以及 Jenkins 是否配置了 HTTP 代理系统管理 - 插件管理 - 高级 - HTTP 代理。如果 Jenkins 需要通过代理访问外网但 Nexus 在内网可能需要配置“No Proxy Host”列表。6.3 解决 “Could not find artifact” 类错误有时错误信息类似Could not find artifact com.xxx:yyy:pom:1.0 in nexus。这通常发生在上传时插件会先尝试从 Nexus 下载该组件的 POM 文件如果存在进行一些元数据合并操作。如果网络或权限导致这一步失败整个上传就会中断。权限问题确保 Jenkins 凭证用户对目标仓库至少有“读取”权限。上传过程需要读元数据。首次上传如果是全新的组件首次上传这个错误可能是无害的。你可以尝试在nexusArtifactUploader步骤中增加一个可选参数skipErrorOnMissingPom: true请注意参数名称可能随插件版本变化需查阅最新文档。但这可能掩盖真正的问题建议优先解决权限问题。检查 Nexus 日志Nexus 的nexus.log会记录更详细的错误信息例如具体的权限验证失败原因这是排查问题的金钥匙。6.4 插件版本兼容性与配置项变化Nexus Platform Plugin 本身也在迭代。不同版本间的参数名称或行为可能有细微差别。例如早期版本可能使用nexusUrl参数而现在集成到nexusInstanceId。当你在网上搜索解决方案时务必留意对应的插件版本。一个良好的习惯是在 Jenkins 的“插件管理”页面中查看你已安装的 Nexus Platform Plugin 的版本号并前往其官方文档页面通常是 GitHub 仓库的 Wiki查阅对应版本的参数说明。直接复制老旧教程的代码片段往往是配置失败的根源。7. 集成到完整 CI/CD 流水线的实践思考将制品上传到 Nexus 不应是一个孤立的步骤而应融入完整的质量关卡中。在我的实践中通常会设计这样的流水线阶段构建与单元测试mvn clean compile test。此阶段产出代码编译结果和单元测试报告。集成测试与质量扫描可能启动依赖服务进行集成测试同时用 SonarQube 进行代码质量分析。只有通过质量阈才能进入下一阶段。构建制品mvn package -DskipTests。此阶段生成最终的 Jar/War 包。上传制品至 Nexus即本文的核心内容。将上一步产出的、经过测试和质量检查的包上传到 Nexus 的 Snapshot 或 Release 仓库。部署到测试环境从 Nexus 拉取刚刚上传的特定版本的制品部署到集成测试或预发布环境。自动化验收测试针对已部署的应用进行端到端测试。生产发布手动或自动触发将 Nexus Release 仓库中的制品部署到生产环境。在这个流程中Nexus 成为了唯一可信的制品源。无论是测试环境还是生产环境都从 Nexus 拉取同一个二进制包确保了环境间的一致性真正实现了“构建一次到处运行”。而 Jenkins 与 Nexus 插件的无缝集成正是自动化这一流程的关键齿轮。