使用Docker搭建私有PyPI鏡像倉庫的完整步驟教學
在企業(yè)內網或離線開發(fā)環(huán)境中,我們常常需要一個穩(wěn)定、快速且可控制的 Python 包管理方案。本文將詳細介紹如何使用 devpi 和 Docker 構建一個私有的 PyPI 鏡像服務器,并實現對 Windows 與 Linux 平臺的 64 位二進制包(wheel) 的自動下載、緩存和分發(fā)。
通過本教程,你可以:
- 快速搭建本地 PyPI 緩存服務器;
- 支持不同操作系統(tǒng)平臺(win_amd64 / manylinux);
- 自動從國內鏡像源(阿里云)預下載指定依賴包;
- 實現高效、安全的企業(yè)級 Python 包管理。
準備工作
1. 創(chuàng)建項目結構
首先,在你的項目目錄中創(chuàng)建以下文件結構:
pypi-mirror/
├── init/
│ ├── Dockerfile
│ └── setup-devpi.sh
├── docker-compose.yml
├── requirements.txt # 待安裝的包列表
└── devpi-data/ # 數據持久化目錄(自動生成)
注意:首次運行前需手動創(chuàng)建空的 devpi-data 目錄用于存儲 devpi 數據。
2. 編寫 Dockerfile(./init/Dockerfile)
# 使用 Python 3.10 作為基礎鏡像(國內加速)
FROM python:3.10
# 設置環(huán)境變量,使用阿里云 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
# 創(chuàng)建數據目錄
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 -e
echo "配置 devpi 客戶端..."
devpi use http://localhost:3141
# 創(chuàng)建用戶
echo "創(chuàng)建用戶和索引..."
devpi user -c mirroruser password=securepassword123 || echo "用戶已存在"
# 登錄該用戶(關鍵步驟!否則無法操作索引)
echo "登錄新創(chuàng)建的用戶..."
devpi login mirroruser --password=securepassword123
# 創(chuàng)建主索引
devpi index -c main bases=root/pypi || echo "索引已存在"
# 切換到主索引
devpi use mirroruser/main
# 創(chuàng)建臨時目錄
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
# 第三階段:創(chuàng)建平臺專用索引
echo "創(chuàng)建平臺過濾索引..."
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)"
安全建議:
- 生產環(huán)境下應修改默認密碼;
- 可啟用 HTTPS 和認證機制增強安全性。
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
"
功能說明:
- 第一次啟動時自動初始化 devpi 數據目錄;
- 后續(xù)啟動直接復用已有數據;
- 腳本延遲執(zhí)行確保服務已就緒;
- 支持容器重啟后自動恢復服務。
獲取熱門包列表并生成 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;
- 執(zhí)行
setup-devpi.sh腳本,下載并上傳包; - 創(chuàng)建平臺專用索引。
時間消耗:取決于 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文件; - 安裝速度快,穩(wěn)定性高。
日常使用命令
| 命令 | 說明 |
|---|---|
| docker-compose up | 啟動服務(無需重建) |
| docker-compose down | 停止并移除容器 |
| docker-compose logs | 查看日志調試問題 |
數據已掛載至 ./devpi-data,即使刪除容器也不會丟失已緩存的包。
高級特性與擴展建議
支持更多平臺
可以擴展腳本支持其他平臺,例如:
macosx_11_0_arm64(M1/M2 Mac)linux_aarch64
只需添加對應的 --platform 參數即可。
定期更新包
可通過定時任務拉取新版本包,保持私有倉庫同步。
添加身份驗證與權限控制
devpi 支持細粒度用戶權限管理,可用于團隊協(xié)作場景。
集成 CI/CD 流程
在內部 CI 環(huán)境中設置此鏡像為默認源,避免外部依賴風險。
總結
本文介紹了一種完整的解決方案,利用 devpi + Docker + 阿里云鏡像 + 多平臺 wheel 分發(fā) 技術棧,打造了一個高性能、跨平臺、可持久化的私有 PyPI 倉庫。
適用場景:
- 企業(yè)內網隔離環(huán)境;
- 開發(fā)團隊統(tǒng)一依賴管理;
- 提升 CI/CD 構建效率;
- 減少對外部源的依賴與安全風險。
核心優(yōu)勢:
- 自動化初始化流程;
- 支持平臺差異化索引;
- 國內鏡像加速下載;
- 易于部署與維護。
現在就開始搭建屬于你自己的私有 PyPI 倉庫吧!
GitHub 參考資源:
- Devpi 官方文檔: https://doc.devpi.net
- Top PyPI Packages 統(tǒng)計: https://hugovk.github.io/top-pypi-packages/
- 阿里云 PyPI 鏡像: https://mirrors.aliyun.com/pypi/simple/
到此這篇關于使用Docker搭建私有PyPI鏡像倉庫的完整步驟教學的文章就介紹到這了,更多相關Docker搭建私有PyPI鏡像倉庫內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
用docker搭建selenium grid分布式環(huán)境實踐之路
這篇文章主要介紹了用docker搭建selenium grid分布式環(huán)境實踐之路,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-03-03
使用Nexus創(chuàng)建Docker倉庫的方法步驟
這篇文章主要介紹了使用Nexus創(chuàng)建Docker倉庫的方法步驟,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-12-12
私有云存儲Minio Docker鏡像無法啟動,提示:Adding local Minio
使用Minio在本地搭建私有云存儲時出現無法啟動,查看日志頻繁輸出“Adding local Minio host to 'mc' configuration...”,然后停止了,本文給大家分享私有云存儲Minio Docker鏡像無法啟動,提示:Adding local Minio host to 'mc' configuration,感興趣的朋友一起看看吧2023-11-11
docker 使用mysqldump命令備份導出項目中的mysql數據
這篇文章主要介紹了docker 使用mysqldump命令備份導出項目中的mysql數據本文通過命令給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2019-12-12
docker搭建zookeeper集群和kafka集群并使用Java測試詳解
本文詳細介紹了如何在Linux虛擬機中使用Docker搭建Kafka集群環(huán)境,并通過Kafka-Manager進行可視化管理,文章包括了從鏡像拉取、容器網絡設置、Zookeeper和Kafka集群搭建到測試和使用Java連接集群的全過程2026-01-01
解決docker run 或者 docker restart 啟動鏡像就自動退出
這篇文章主要介紹了解決docker run 或者 docker restart 啟動鏡像就自動退出的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-11-11

