使用 Docker 搭建私有 PyPI 镜像仓库:支持多平台二进制包同步
docker
在企业内网或离线开发环境中,我们常常需要一个稳定、快速且可控制的 Python 包管理方案。本文将详细介绍如何使用 devpi
和 Docker 构建一个私有的 PyPI 镜像服务器,并实现对 Windows 与 Linux 平台的 64 位二进制包(wheel) 的自动下载、缓存和分发。
通过本教程,你可以:
- 快速搭建本地 PyPI 缓存服务器;
- 支持不同操作系统平台(win_amd64 / manylinux);
- 自动从国内镜像源(阿里云)预下载指定依赖包;
- 实现高效、安全的企业级 Python 包管理。
🛠️ 准备工作
1. 创建项目结构
首先,在你的项目目录中创建以下文件结构:
pypi-mirror/
├── init/
│ ├── Dockerfile
│ └── setup-devpi.sh
├── docker-compose.yml
├── requirements.txt # 待安装的包列表
└── devpi-data/ # 数据持久化目录(自动生成)
⚠️ 注意:首次运行前需手动创建空的
devpi-data
目录用于存储 devpi 数据。
2. 编写 Dockerfile(./init/Dockerfile
)
# 使用 Python 3.10 作为基础镜像(国内加速)
FROM python:3.10# 设置环境变量,使用阿里云 PyPI 镜像
ENV PIP_DEFAULT_TIMEOUT=100 \PIP_RETRIES=5 \PIP_INDEX_URL=https://mirrors.aliyun.com/pypi/simple/ \PIP_TRUSTED_HOST=mirrors.aliyun.com# 安装 devpi 相关组件
RUN pip install --no-cache-dir devpi-server devpi-web devpi-client passlib# 创建数据目录
RUN mkdir -p /data/server# 暴露端口
EXPOSE 3141# 启动 devpi-server
CMD ["devpi-server", "--host", "0.0.0.0", "--port", "3141", "--serverdir", "/data/server"]
📌 说明:
- 使用阿里云镜像提升国内网络下载速度。
- 安装了
devpi-server
(服务端)、devpi-web
(Web 界面)、devpi-client
(命令行工具)。 - 所有数据保存在
/data/server
,通过卷挂载实现持久化。
3. 编写初始化脚本(./init/setup-devpi.sh
)
该脚本负责配置 devpi 用户、索引,并根据 requirements.txt
下载并上传指定包及其依赖。
#!/bin/bash
set -eecho "配置 devpi 客户端..."
devpi use http://localhost:3141# 创建用户
echo "创建用户和索引..."
devpi user -c mirroruser password=securepassword123 || echo "用户已存在"# 登录该用户(关键步骤!否则无法操作索引)
echo "登录新创建的用户..."
devpi login mirroruser --password=securepassword123# 创建主索引
devpi index -c main bases=root/pypi || echo "索引已存在"# 切换到主索引
devpi use mirroruser/main# 创建临时目录
mkdir -p /tmp/packages# 设置 pip 使用阿里云镜像
export PIP_INDEX_URL="https://mirrors.aliyun.com/pypi/simple/"
export PIP_TRUSTED_HOST="mirrors.aliyun.com"echo "开始处理 requirements.txt 中的包..."# 检查 requirements.txt 是否存在
if [ ! -f "/app/requirements.txt" ]; thenecho "错误: /app/requirements.txt 文件不存在!"exit 1
fi# 第一阶段:解析所有包及依赖
all_packages=()
while IFS= read -r package; do[[ -z "$package" || "$package" =~ ^# ]] && continueecho "分析包: $package"# 获取依赖(模拟安装但不实际安装)dependencies=$(pip install --no-deps --dry-run "$package" 2>&1 | grep 'Collecting' | awk '{print $2}' | sed 's/[<=>].*//')all_packages+=("$package")while IFS= read -r dep; do[[ -z "$dep" ]] && continueall_packages+=("$dep")done <<< "$dependencies"
done < /app/requirements.txt# 去重排序
unique_packages=($(printf "%s\n" "${all_packages[@]}" | sort -u))# 第二阶段:下载 64 位平台 wheel 包
echo "正在下载 64 位平台二进制包..."
for package in "${unique_packages[@]}"; doecho "处理 $package..."rm -f /tmp/packages/* # 清空临时目录# 下载 Windows 64-bit 包(Python 3.13 兼容)echo " 下载 win_amd64 版本..."pip download --only-binary=:all: --python-version 313 --platform win_amd64 \-i https://mirrors.aliyun.com/pypi/simple/ -d /tmp/packages "$package" > /dev/null 2>&1# 下载 Linux x86_64 包(manylinux)echo " 下载 manylinux_2_17_x86_64 版本..."pip download --only-binary=:all: --python-version 313 --platform manylinux_2_17_x86_64 \-i https://mirrors.aliyun.com/pypi/simple/ -d /tmp/packages "$package" > /dev/null 2>&1# 上传到 devpifor whl in /tmp/packages/*.whl; doif [ -f "$whl" ]; thenecho " 上传 $whl 到私有仓库..."devpi upload "$whl"fidone
done# 第三阶段:创建平台专用索引
echo "创建平台过滤索引..."devpi index -c win_amd64 bases=main \mirrorsync=1 \platform=win_amd64 \python_version=3.13 || echo "索引 win_amd64 已存在"devpi index -c linux_x86_64 bases=main \mirrorsync=1 \platform=manylinux_2_17_x86_64 \python_version=3.13 || echo "索引 linux_x86_64 已存在"echo "✅ 初始化完成!DevPI 私有仓库已就绪。"echo ""
echo "📌 使用方式如下:"
echo " Windows 用户:"
echo " pip install -i http://<YOUR_LOCAL_IP>:3141/mirroruser/win_amd64/+simple/ <package>"
echo ""
echo " Linux 用户:"
echo " pip install -i http://<YOUR_LOCAL_IP>:3141/mirroruser/linux_x86_64/+simple/ <package>"
echo ""
echo "💡 提示:请将 <YOUR_LOCAL_IP> 替换为宿主机 IP 地址(如 192.168.1.100)"
🔐 安全建议:
- 生产环境下应修改默认密码;
- 可启用 HTTPS 和认证机制增强安全性。
4. 配置 Docker Compose(docker-compose.yml
)
version: '3.8'services:devpi:build:context: .dockerfile: init/Dockerfilecontainer_name: pypi-mirrorports:- "3141:3141"volumes:- ./devpi-data:/data/server- ./init/setup-devpi.sh:/setup-devpi.sh- ./requirements.txt:/app/requirements.txtenvironment:- DEVPISERVER_SERVERDIR=/data/serverrestart: unless-stoppedentrypoint: >sh -c "if [ ! -f /data/server/.serverversion ]; thendevpi-init --serverdir /data/server;fi;devpi-server --host 0.0.0.0 --port 3141 --serverdir /data/server &sleep 20 &&/setup-devpi.sh &&wait"
📌 功能说明:
- 第一次启动时自动初始化 devpi 数据目录;
- 后续启动直接复用已有数据;
- 脚本延迟执行确保服务已就绪;
- 支持容器重启后自动恢复服务。
📥 获取热门包列表并生成 requirements.txt
为了构建一个实用的私有镜像,我们可以基于 PyPI 上最受欢迎的包 来填充初始内容。
步骤一:下载 top-pypi-packages.csv
访问 https://hugovk.github.io/top-pypi-packages/
点击 “Download CSV” 下载最新的 top-pypi-packages.csv
文件。
步骤二:使用 gen_requirements.py 生成 requirements.txt
假设你有一个脚本 gen_requirements.py
,其功能是从 CSV 中提取前 N 个最流行包名,输出为 requirements.txt
。
示例代码(gen_requirements.py
):
import csv# 读取 top-pypi-packages.csv,提取前 50 个包
with open('top-pypi-packages.csv', newline='', encoding='utf-8') as f:reader = csv.DictReader(f)packages = [row['project'] for row in reader]# 写入 requirements.txt
with open('requirements.txt', 'w') as f:for pkg in packages[:50]: # 取前 50 名f.write(f"{pkg}\n")print("✅ 已生成 requirements.txt,包含前 50 个热门 PyPI 包")
运行后生成的 requirements.txt
示例:
requests
urllib3
certifi
idna
charset_normalizer
click
flask
...
▶️ 启动服务
第一步:构建并启动容器
docker-compose up --build
首次运行会经历以下过程:
- 构建镜像;
- 初始化 devpi 数据目录;
- 启动 devpi-server;
- 执行
setup-devpi.sh
脚本,下载并上传包; - 创建平台专用索引。
⏳ 时间消耗:取决于 requirements.txt
中包的数量和网络速度,可能需要数分钟。
第二步:查看 Web 界面
打开浏览器访问:
👉 http://localhost:3141/mirroruser/main/+simple/
你将看到所有已上传包的简单索引页面。
💻 客户端安装测试
Windows 用户
pip install -i http://192.168.1.100:3141/mirroruser/win_amd64/+simple/ requests
Linux 用户
pip install -i http://192.168.1.100:3141/mirroruser/linux_x86_64/+simple/ pandas
✅ 成功标志:
- 不再连接公网 PyPI;
- 直接从本地服务器下载
.whl
文件; - 安装速度快,稳定性高。
🔁 日常使用命令
命令 | 说明 |
---|---|
docker-compose up | 启动服务(无需重建) |
docker-compose down | 停止并移除容器 |
docker-compose logs | 查看日志调试问题 |
✅ 数据已挂载至
./devpi-data
,即使删除容器也不会丢失已缓存的包。
🧩 高级特性与扩展建议
✅ 支持更多平台
可以扩展脚本支持其他平台,例如:
macosx_11_0_arm64
(M1/M2 Mac)linux_aarch64
只需添加对应的 --platform
参数即可。
✅ 定期更新包
可通过定时任务拉取新版本包,保持私有仓库同步。
✅ 添加身份验证与权限控制
devpi 支持细粒度用户权限管理,可用于团队协作场景。
✅ 集成 CI/CD 流程
在内部 CI 环境中设置此镜像为默认源,避免外部依赖风险。
📌 总结
本文介绍了一种完整的解决方案,利用 devpi + Docker + 阿里云镜像 + 多平台 wheel 分发
技术栈,打造了一个高性能、跨平台、可持久化的私有 PyPI 仓库。
🎯 适用场景:
- 企业内网隔离环境;
- 开发团队统一依赖管理;
- 提升 CI/CD 构建效率;
- 减少对外部源的依赖与安全风险。
🔧 核心优势:
- 自动化初始化流程;
- 支持平台差异化索引;
- 国内镜像加速下载;
- 易于部署与维护。
🚀 现在就开始搭建属于你自己的私有 PyPI 仓库吧!
GitHub 参考资源:
- Devpi 官方文档: https://doc.devpi.net
- Top PyPI Packages 统计: https://hugovk.github.io/top-pypi-packages/
- 阿里云 PyPI 镜像: https://mirrors.aliyun.com/pypi/simple/
如有疑问,欢迎留言交流!