3、私有包仓库搭建:使用Nexus搭建私有PyPI仓库
说实话,做SDK发布最头疼的事是什么?
不是写代码,是包管理。
你想想看,公司内部几十个SDK模块,全扔到公共PyPI上?不合适。自己搞个文件服务器存whl包?版本乱成一锅粥。我经历过那种「这个包是谁传的?版本号怎么对不上?」的噩梦,后来才下定决心——必须上私有仓库。
今天咱们就聊聊怎么用Nexus搭一个靠谱的私有PyPI仓库。这东西我用了好几年,踩过坑,也总结了些经验,分享给你。
3.1 为什么选Nexus?
市面上的私有仓库方案不少,比如pypiserver、devpi、Artifactory。我个人习惯用Nexus,原因有三:
- 全能型选手:不光管PyPI,还能管npm、Docker、Maven。一个服务搞定所有包类型
- 权限控制成熟:LDAP集成、角色管理、仓库级别的读写权限,企业级需求都能满足
- 社区版够用:免费版的功能已经覆盖了90%的日常场景
我在项目中遇到过团队用pypiserver,结果权限全靠文件系统控制,后来有人误删了包,回滚都找不到版本。从那以后,我对权限管理就特别敏感。
3.2 安装与初始化
Nexus的安装方式很多,我推荐用Docker,省心。
# 拉取镜像
docker pull sonatype/nexus3:latest
# 启动容器
docker run -d \
--name nexus \
-p 8081:8081 \
-p 8082:8082 \
-v /data/nexus:/nexus-data \
sonatype/nexus3:latest
启动后访问 http://localhost:8081,默认管理员账号是 admin,密码在容器里的 /nexus-data/admin.password 文件中。
3.3 创建PyPI仓库
Nexus的仓库类型有三种,咱们得先搞清楚:
| 仓库类型 | 说明 | 用途 |
|---|---|---|
| hosted | 托管私有包 | 存放公司内部开发的SDK |
| proxy | 代理公共仓库 | 缓存PyPI官方包,加速下载 |
| group | 组合多个仓库 | 把hosted和proxy合并成一个地址 |
我一般会建三个仓库:
- pypi-hosted:私有包存放地
- pypi-proxy:代理
https://pypi.org - pypi-group:把上面两个组合起来
操作步骤很简单:
1. 登录Nexus Web界面
2. 点击左侧「Repositories」→「Create repository」
3. 选择「pypi (hosted)」
4. 填写名称:pypi-hosted
5. 部署策略选「Allow redeploy」(允许覆盖,方便调试)
6. 点击「Create repository」
3.4 配置认证与权限
仓库建好了,不能谁都能上传吧?
Nexus的权限模型分三层:用户 → 角色 → 权限。我习惯这样配:
3.4.1 创建角色
角色名:pypi-developer
权限:
- nx-repository-view-pypi-*-browse
- nx-repository-view-pypi-*-read
- nx-repository-view-pypi-*-edit
角色名:pypi-admin
权限:
- nx-repository-view-pypi-*-*
- nx-repository-admin-pypi-*-*
3.4.2 创建用户并分配角色
用户名:sdk-publisher
角色:pypi-admin
用途:CI/CD流水线使用
用户名:sdk-developer
角色:pypi-developer
用途:开发人员下载包
嗯,这里要注意:密码别写在代码里。我一般用CI/CD的密钥管理服务,或者Nexus自带的「User Token」功能。
3.5 上传私有包
上传包需要配置 ~/.pypirc 文件:
[distutils]
index-servers =
nexus
[nexus]
repository: http://localhost:8081/repository/pypi-hosted/
username: sdk-publisher
password: your-password
然后就可以上传了:
# 构建包
python setup.py sdist bdist_wheel
# 上传到私有仓库
twine upload --repository nexus dist/*
我在项目中遇到过一个问题:上传时提示 403 Forbidden。排查了半天,发现是用户权限没配好,少给了 edit 权限。所以上传前先确认角色权限。
3.6 下载私有包
下载就简单了,配置 pip.conf 指向group仓库:
[global]
index-url = http://localhost:8081/repository/pypi-group/simple/
trusted-host = localhost
# 如果需要认证
[install]
extra-index-url = http://sdk-publisher:password@localhost:8081/repository/pypi-group/simple/
然后正常使用pip:
pip install my-private-sdk==1.0.0
为什么用group仓库而不是直接指向hosted?因为group仓库会先查私有包,找不到再去公共PyPI拉,这样你只需要配一个源地址。
3.7 核心逻辑流程图
下面这张图是我画的私有包仓库整体架构,你看一眼就明白了:
3.8 避坑指南
最后分享几个我踩过的坑:
坑1:版本号规范
私有包版本号一定要遵循PEP 440规范。我曾经用 1.0.0-beta 这种格式,结果pip解析失败。正确写法是 1.0.0b1。
坑2:仓库清理策略
Nexus默认不会自动清理旧版本。时间长了磁盘会爆。建议设置「Cleanup Policies」,保留最近10个版本,或者保留90天内的版本。
坑3:HTTPS配置
生产环境一定要配HTTPS。我见过有人用HTTP传输,密码被中间人抓包。Nexus支持反向代理,用Nginx加个证书就行。
好了,私有PyPI仓库的搭建就聊到这儿。这套方案我在多个项目里验证过,稳定可靠。你照着做,基本不会出大问题。
可可精品资料库