Docker搭建Maven私服
前言
搭建私有maven仓库 (opens new window)适合在协同工作时,如:A项目是公司的工具包,B项目中会引入A install后形成的jar包,但是其他同事本地运行也要和你一样的操作吗?到线上运行也要一样的操作吗?所以,这类型产生的jar包需要一个统一的地方来进行管理,只需把A的jar包部署推送到私有maven仓库中,B项目在pom文件中引入依赖即可。
# 一、Nexus 仓库系统简介
- 官网:https://help.sonatype.com/repomanager3 (opens new window)
- Nexus 是什么:
- Nexus 是一款非常流行的 仓库管理系统,用于管理和分发各种软件包、依赖项、构建工件等。它是一个基于 Java 的 开源软件 (opens new window),最初由 Sonatype 开发,并在 Apache 许可证下发布。
- 在现代软件开发中,项目经常需要使用大量第三方依赖和库,Nexus 能帮助开发团队在一个统一的地方集中管理所有依赖,避免重复下载、加快构建速度,并确保依赖项的稳定性和一致性。
# 二、Docker 安装 Nexus 仓库
# 1. 拉取 Nexus 镜像
首先从 Docker Hub 拉取最新版本的 Nexus 3 镜像:
# 拉取 sonatype/nexus3 镜像,latest 代表最新版本
docker pull sonatype/nexus3:latest
2
# 2. 创建挂载目录并设置权限
为了确保 Nexus 数据能够持久化,我们需要将数据挂载到宿主机的指定目录:
# 创建数据存储目录
mkdir /data/nexus-data
# 设置目录权限,确保 Nexus 可以读写该目录(200 是 Nexus 的默认用户 ID)
chown -R 200 /data/nexus-data
2
3
4
5
# 3. 启动 Nexus 容器
使用 Docker 启动 Nexus 容器,并设置相关参数:
docker run -d -p 8081:8081 --name nexus \ # 后台运行,并将容器命名为 nexus,映射端口 8081
--restart=always \ # 设置容器在停止后自动重启
-e INSTALL4J_ADD_VM_PARAMS="-Xms512m -Xmx512m \ # 设置 JVM 最小和最大堆内存为 512MB
-XX:MaxDirectMemorySize=1200m" \ # 设置最大直接内存大小为 1200MB
-v /data/nexus-data:/nexus-data sonatype/nexus3 # 挂载宿主机目录到容器内的 /nexus-data
2
3
4
5
纯净版本可以直接复制到服务器使用
docker run -d -p 8081:8081 --name nexus \
--restart=always \
-e INSTALL4J_ADD_VM_PARAMS="-Xms512m -Xmx512m \
-XX:MaxDirectMemorySize=1200m" \
-v /data/nexus-data:/nexus-data sonatype/nexus3
2
3
4
5
# 4. 查看容器运行日志(可选)
可以通过以下命令实时查看 Nexus 容器的运行日志,确认启动是否成功:
# 实时追加最新日志,查看日志的最后 100 行
docker logs -f --tail=100 nexus
2
# 三、Nexus 用户登录
Nexus 安装成功后,初始的管理员账号为 admin
,但默认密码需要在挂载的目录中查找。
进入挂载目录
/data/nexus-data
:cd /data/nexus-data
1查看
admin.password
文件:# 显示 admin 密码 cat admin.password
1
2复制密码后,可以使用
admin
账号和密码登录 Nexus。
# 修改登录端口号
访问Nexus 主界面需要改一下配置文件的的端口。
配图示例:
修改成功后,打开浏览器访问 http://<你的IP>:8081
,即可进入 Nexus 主界面。
# 四、Nexus 仓库类型详细介绍
在 Nexus 中,仓库分为三种主要类型,每种类型的功能和应用场景不同,以下是详细介绍:
Proxy 仓库(代理仓库):
代理仓库用于代理外部的公共仓库(如 Maven 中央仓库)。当你请求某个依赖时,Nexus 会通过代理仓库向外部仓库拉取该依赖,并将其缓存到本地。之后的请求会直接从缓存中提供该依赖,减少外网访问并提升下载速度。Hosted 仓库(宿主仓库):
宿主仓库是用于存储企业内部或私有的构件和依赖。通常分为两个子类型:- Releases(发行版仓库):用于存储稳定版本的依赖(即发布版本)。这些依赖通常是经过测试、验证并正式发布的。
- Snapshots(快照版仓库):用于存储开发阶段的快照版本。快照版表示代码仍在开发过程中,并不稳定。快照版本不能上传到发行版仓库,Nexus 会强制进行这方面的限制。
Group 仓库(仓库组):
仓库组将多个仓库组合在一起,提供一个统一的访问入口。当请求依赖时,仓库组会依次遍历其中的仓库,直到找到所需的依赖。Group 仓库通常用于简化 Maven 配置,比如可以将maven-central
、releases
和snapshots
仓库组合在一个 Group 中,只需配置一个仓库地址即可访问所有依赖。
仓库格式
- Maven 2:Maven 2 是 Java 开发中最常见的依赖管理格式,也是 Nexus 中的主要仓库格式。
- NuGet:主要用于 .NET 开发中的依赖管理。
# 默认的 Group 仓库组
Nexus 自带一个默认的 Group 仓库 maven-public
,它将 central
、releases
和 snapshots
三个仓库都包含在其中。这意味着,你可以通过一个统一的 URL 访问所有这三个仓库中的依赖。
# 五、创建 Proxy 仓库(代理仓库)
创建代理仓库是 Nexus 常见的使用场景之一,例如创建一个代理 Maven 中央仓库或阿里云 Maven 仓库的 Proxy 仓库。
创建 Proxy 仓库的步骤
选择创建仓库: 在 Nexus 管理界面,点击 Create repository,选择 proxy 类型的仓库。
配置 Proxy 仓库: 设置仓库名称(如
aliyun-maven
),并填写代理仓库的远程 URL。以下是代理阿里云 Maven 仓库的示例配置:https://maven.aliyun.com/nexus/content/groups/public
1设置版本策略、缓存策略等:
- Version Policy(版本策略):选择
Mixed
,支持代理 Release 和 Snapshot 版本。 - Layout Policy(布局策略):选择
Strict
,确保路径符合 Maven 的规范。 - Remote Storage:填写远程仓库的 URL,例如阿里云 Maven 仓库。
- Version Policy(版本策略):选择
Proxy 仓库的使用优势
- 本地缓存:代理仓库会缓存外部仓库中的依赖,减少重复下载,提升构建速度。
- 统一管理:企业可以通过一个 Nexus 私服管理所有外部依赖,确保依赖版本的稳定性和可控性。
- 网络优化:通过代理本地化常用依赖,降低外网带宽消耗和网络延迟。
# 六、上传依赖到 Nexus 仓库(重点)
在实际开发中,经常需要将自己编写的组件、库或模块上传到 Nexus 私服仓库中,以便团队内部共享。以下是如何将依赖上传到 Nexus 仓库的详细步骤。
# 1. 配置本地 Maven 的 settings.xml
首先,需要在本地 Maven 的 settings.xml
中配置访问 Nexus 私服的凭证信息:
<servers>
<!-- 这是配置访问私有仓库的用户名密码 -->
<server>
<!-- id 标签可以随便填,只需在 pom.xml 中保持一致 -->
<id>nexus-scholar</id>
<username>dev</username>
<password>dev</password>
</server>
</servers>
2
3
4
5
6
7
8
9
id
:唯一标识该仓库配置,需要与pom.xml
中的distributionManagement
部分一致。username
和password
:用于访问 Nexus 仓库的用户名和密码。
# 2. 在要上传的模块的 pom.xml
中添加 distributionManagement
配置
在项目的 pom.xml
文件中配置仓库上传信息:
<distributionManagement>
<repository>
<!-- id要和setting.xml中的保持一致 -->
<id>nexus-scholar</id>
<url>https://nexus.wym123.cn/repository/maven-releases/</url>
</repository>
<snapshotRepository>
<id>nexus-scholar</id>
<url>https://nexus.wym123.cn/repository/maven-snapshots/</url>
</snapshotRepository>
</distributionManagement>
2
3
4
5
6
7
8
9
10
11
repository
标签:用于指定发布(release)版本的上传仓库。snapshotRepository
标签:用于指定快照(snapshot)版本的上传仓库。
Nexus 会根据模块的版本号自动选择上传到哪个仓库。如果版本号带有
SNAPSHOT
(如:1.0.0-SNAPSHOT
),则会上传到snapshot
仓库;如果版本号不包含SNAPSHOT
,如1.0.0
,则会上传到release
仓库。
id
:应与settings.xml
中的server id
保持一致。url
:指定具体的仓库地址,可以通过 Nexus 管理界面获取。例如:-
http://ip:port/repository/maven-releases/
1
# 3. 配置 Nexus 仓库中的 Allow redeploy
选项
在 Nexus 中,上传依赖时是否允许覆盖已有版本是非常重要的设置。如下图所示:
- Allow redeploy:允许重新部署已存在的版本。如果选中此选项,即使版本已经存在,也可以上传更新的版本,适用于内部测试环境或需要频繁迭代的场景。
- Disable redeploy:禁止重新部署已存在的版本。如果选择此选项,上传相同版本时会被拒绝。通常适用于生产环境,以防止误操作覆盖已经发布的稳定版本。
# 4. 上传依赖的命令
在配置好以上内容后,可以使用以下 Maven 命令将项目打包并上传到 Nexus 仓库:
mvn clean deploy
clean
:清理项目中的旧构建文件。deploy
:将构建的工件(包括 JAR、POM、源码等)上传到指定的 Nexus 仓库。
# 5. 仓库选择逻辑
- 如果版本号包含
SNAPSHOT
,如<version>1.0.0-SNAPSHOT</version>
,则上传到snapshot
仓库。 - 如果版本号为
<version>1.0.0</version>
,则上传到release
仓库。
# 6. 上传仓库的具体路径配置
在 Nexus 管理界面中,可以复制仓库的 URL,如下图所示:
在 pom.xml
中的 distributionManagement
中配置相应的 URL:
<url>http://ip:port/repository/maven-releases/</url>
<url>http://ip:port/repository/maven-snapshots/</url>
2
# 7. 仓库设置的注意事项
Nexus 提供了 Allow redeploy
选项,用于控制是否允许覆盖已经存在的版本:
- 适用场景:
- 允许覆盖:适用于测试环境、内部开发过程。
- 禁止覆盖:适用于生产环境,避免稳定版本被误覆盖。
通过正确配置以上内容,你可以顺利将依赖上传到 Nexus 仓库并共享给团队使用。
# 七、下载依赖配置(重点)
在实际项目中,为了使用自建的 Nexus 私服仓库下载依赖,同时兼顾外部公共仓库(如 Maven 中央仓库或阿里云仓库),需要在本地的 settings.xml
中进行适当配置。以下是详细步骤和配置说明。
# 1. 配置本地 Maven 的 settings.xml
在本地 Maven 的 settings.xml
文件中,找到 <mirrors>
标签,并在其中添加私服和外部仓库的镜像配置。
<mirrors>
<!-- 私有仓库的配置 -->
<mirror>
<!-- id 是唯一标识,可以任意填写 -->
<id>opals-maven</id>
<!-- mirrorOf 为 * 表示代理所有仓库请求 -->
<mirrorOf>*</mirrorOf>
<!-- 这里填写 Nexus 私服的仓库组 URL -->
<url>http://your-nexus-server:port/repository/maven-public/</url>
<!-- 仓库布局 -->
<layout>default</layout>
</mirror>
<!-- 阿里云代理仓库的配置,当私服找不到依赖时会访问这里 -->
<mirror>
<!-- id 是唯一标识,可以任意填写 -->
<id>nexus-aliyun</id>
<!-- mirrorOf 为 central 表示仅代理 Maven 中央仓库的请求 -->
<mirrorOf>central</mirrorOf>
<name>Nexus aliyun</name>
<!-- 阿里云公共 Maven 仓库 URL -->
<url>https://maven.aliyun.com/nexus/content/groups/public</url>
<!-- 仓库布局 -->
<layout>default</layout>
</mirror>
</mirrors>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
配置说明
id
:唯一标识镜像配置,可以自定义,但需要唯一。例如opals-maven
、nexus-aliyun
。mirrorOf
:指定该镜像代理的仓库:- 使用
*
表示代理所有仓库请求。 - 使用
central
仅代理 Maven 中央仓库。
- 使用
url
:指定镜像仓库的地址:- 自建 Nexus 仓库组的 URL,例如:
http://your-nexus-server:port/repository/maven-public/
。 - 阿里云公共 Maven 仓库的 URL:
https://maven.aliyun.com/nexus/content/groups/public
。
- 自建 Nexus 仓库组的 URL,例如:
layout
:通常为default
,表示标准 Maven 仓库布局。
# 2. 在 pom.xml
中配置私服仓库
- 如果你不想在全局的
settings.xml
中配置私服仓库地址,而是希望在具体的项目中直接配置私服地址,可以在项目的pom.xml
文件中配置私服仓库地址。 - 通过在
pom.xml
中的<repositories>
和<pluginRepositories>
标签配置私服地址,Maven 会在项目构建时优先使用这些配置的仓库进行依赖解析。
<repositories>
<!-- 配置私服仓库 -->
<repository>
<!-- 私服的唯一id -->
<id>opals-maven</id>
<url>http://your-nexus-server:port/repository/maven-public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<!-- 配置插件的私服仓库 -->
<pluginRepository>
<id>opals-maven-plugins</id>
<url>http://your-nexus-server:port/repository/maven-public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
配置说明
<repositories>
:指定项目在下载依赖时使用的仓库列表。<pluginRepositories>
:指定项目在下载 Maven 插件时使用的仓库列表。<id>
:仓库的唯一标识符,可以任意设置,但需要唯一。<url>
:指定私服仓库的地址,如 Nexus 中的仓库组或具体的 hosted 仓库地址。<releases>
和<snapshots>
:用于分别配置发布版本和快照版本的启用状态。
# 3. Nexus 私服与外部仓库的关系
- 优先使用私服仓库:在配置中,Nexus 私服仓库组(
maven-public
)配置在前,因此 Maven 在请求依赖时会优先从私服仓库中查找。如果找不到,才会向后面的阿里云仓库发起请求。 - 镜像链配置:这种配置可以确保如果私服找不到某些依赖,Maven 仍然可以从外部仓库(如阿里云)获取,保证构建不受影响。
配图示例
# 4. 仓库的重要概念和 API 说明
仓库组(Group Repository):仓库组将多个仓库整合到一个统一的访问入口。通过访问仓库组,可以遍历其中的各个仓库查找依赖,大大简化了配置。例如,在 Nexus 中
maven-public
是一个常见的仓库组,它包含了maven-central
、releases
和snapshots
仓库。Proxy 仓库:用于代理外部公共仓库,例如 Maven 中央仓库或阿里云仓库。配置 Proxy 仓库可以实现缓存依赖、提升下载速度和减轻外网压力。
常用 API 和参数说明
/service/rest/v1/search
:用于查询仓库中的依赖。例如:http://your-nexus-server:port/service/rest/v1/search?repository=maven-public&group=com.example&name=my-artifact&version=1.0.0
1/service/rest/v1/components
:用于上传或删除仓库中的组件。
# 5. 完整配置后的下载流程
当项目需要下载依赖时,Maven 将按照如下顺序进行:
- 先从配置的 Nexus 私服仓库组中查找依赖。
- 如果私服中没有该依赖,则继续尝试从阿里云等公共仓库中查找。
- 下载成功后,依赖会被缓存到本地仓库,加快后续的构建速度。
通过上述配置,可以确保项目依赖既能从私服中获取,也能在必要时从外部仓库下载,确保构建的稳定性和灵活性。
# 八、常见问题汇总
在使用 Nexus 的过程中,可能会遇到一些常见的问题和疑惑。以下是针对这些问题的详细解答和解决方案。
# 1. 如何将新建的仓库添加到组仓库?
有时,我们新建了一个仓库(例如代理仓库或自定义的 hosted 仓库)后,希望将它添加到现有的组仓库中。操作步骤如下:
打开 Nexus 管理界面,点击左侧的 "Repositories"。
在仓库列表中,选择要添加到组仓库的仓库组(例如
maven-public
)。点击 "Settings" 进入配置页面,如下图所示:
在 "Members" 部分,你可以看到当前组仓库包含的所有子仓库。点击 "Add" 按钮,将新建的仓库添加到组仓库中。
保存配置后,新仓库就会成为组仓库的一部分,所有访问组仓库的请求都会遍历这个新仓库。
# 2. Nexus 代理仓库状态说明
在 Nexus 中,代理仓库的状态可以帮助我们了解当前代理的外部仓库是否可用。以下是常见的状态及其含义:
- online-remote available:表示该代理仓库的远程仓库已连接并可用,依赖可以正常下载。
- online-ready to connect:表示当前还没有任何依赖请求过这个代理仓库,Nexus 还不知道该远程仓库是否可用,因此显示为待连接状态。当第一次尝试访问该仓库时,Nexus 会尝试连接远程仓库,并更新状态。
# 3. 推送依赖到 Nexus 提示 405 错误
在将依赖推送到 Nexus 时,遇到以下错误:
Return code is: 405, ReasonPhrase: PUT.
原因分析:
- 该错误通常是由于将依赖推送到了组仓库(group repository)而不是指定的 hosted 仓库。组仓库不支持上传操作,上传操作只能对 hosted 仓库进行。
解决方案:
检查
pom.xml
中的distributionManagement
配置,确保上传的目标是一个 hosted 仓库,而不是组仓库。<distributionManagement> <repository> <!-- id 必须与 settings.xml 中的 id 保持一致 --> <id>opals-maven</id> <!-- 确保这里的 URL 指向的是 hosted 仓库 --> <url>http://ip:port/repository/maven-releases/</url> </repository> <snapshotRepository> <id>opals-maven</id> <url>http://ip:port/repository/maven-snapshots/</url> </snapshotRepository> </distributionManagement>
1
2
3
4
5
6
7
8
9
10
11
12确保配置的 URL 指向的是
maven-releases
或maven-snapshots
,而不是maven-public
这种组仓库。错误配置如图所示:
注意事项:
- 组仓库(group)用于统一访问多个仓库,不支持上传操作。
- hosted 仓库(如
maven-releases
、maven-snapshots
)才是正确的上传目标。