docker

关注公众号 jb51net

关闭
首页 > 网站技巧 > 服务器 > 云和虚拟化 > docker > Docker搭建私有PyPI镜像仓库

使用Docker搭建私有PyPI镜像仓库的完整步骤教学

作者:东方佑

在企业内网或离线开发环境中,我们常常需要一个稳定、快速且可控制的 Python 包管理方案,本文将详细介绍如何使用 devpi 和 Docker 构建一个私有的 PyPI 镜像服务器,有需要的小伙伴可以了解下

在企业内网或离线开发环境中,我们常常需要一个稳定、快速且可控制的 Python 包管理方案。本文将详细介绍如何使用 devpi 和 Docker 构建一个私有的 PyPI 镜像服务器,并实现对 Windows 与 Linux 平台的 64 位二进制包(wheel) 的自动下载、缓存和分发。

通过本教程,你可以:

准备工作

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"]

说明:

3. 编写初始化脚本(./init/setup-devpi.sh)

该脚本负责配置 devpi 用户、索引,并根据 requirements.txt 下载并上传指定包及其依赖。

#!/bin/bash
set -e

echo "配置 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" ]; then
    echo "错误: /app/requirements.txt 文件不存在!"
    exit 1
fi

# 第一阶段:解析所有包及依赖
all_packages=()
while IFS= read -r package; do
  [[ -z "$package" || "$package" =~ ^# ]] && continue
  echo "分析包: $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" ]] && continue
    all_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[@]}"; do
  echo "处理 $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

  # 上传到 devpi
  for whl in /tmp/packages/*.whl; do
    if [ -f "$whl" ]; then
      echo "  上传 $whl 到私有仓库..."
      devpi upload "$whl"
    fi
  done
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)"

安全建议:

4. 配置 Docker Compose(docker-compose.yml)

version: '3.8'

services:
  devpi:
    build:
      context: .
      dockerfile: init/Dockerfile
    container_name: pypi-mirror
    ports:
      - "3141:3141"
    volumes:
      - ./devpi-data:/data/server
      - ./init/setup-devpi.sh:/setup-devpi.sh
      - ./requirements.txt:/app/requirements.txt
    environment:
      - DEVPISERVER_SERVERDIR=/data/server
    restart: unless-stopped
    entrypoint: >
      sh -c "
        if [ ! -f /data/server/.serverversion ]; then
          devpi-init --serverdir /data/server;
        fi;
        devpi-server --host 0.0.0.0 --port 3141 --serverdir /data/server &
        sleep 20 &&
        /setup-devpi.sh &&
        wait
      "

功能说明:

获取热门包列表并生成 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

首次运行会经历以下过程:

时间消耗:取决于 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

成功标志:

日常使用命令

命令说明
docker-compose up启动服务(无需重建)
docker-compose down停止并移除容器
docker-compose logs查看日志调试问题

数据已挂载至 ./devpi-data,即使删除容器也不会丢失已缓存的包。

高级特性与扩展建议

支持更多平台

可以扩展脚本支持其他平台,例如:

只需添加对应的 --platform 参数即可。

定期更新包

可通过定时任务拉取新版本包,保持私有仓库同步。

添加身份验证与权限控制

devpi 支持细粒度用户权限管理,可用于团队协作场景。

集成 CI/CD 流程

在内部 CI 环境中设置此镜像为默认源,避免外部依赖风险。

总结

本文介绍了一种完整的解决方案,利用 devpi + Docker + 阿里云镜像 + 多平台 wheel 分发 技术栈,打造了一个高性能、跨平台、可持久化的私有 PyPI 仓库。

适用场景:

核心优势:

现在就开始搭建属于你自己的私有 PyPI 仓库吧!

GitHub 参考资源:

到此这篇关于使用Docker搭建私有PyPI镜像仓库的完整步骤教学的文章就介绍到这了,更多相关Docker搭建私有PyPI镜像仓库内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文