# 内网pip仓库搭建完整指南
## 一、内网pip仓库搭建方案对比
| 方案类型 | 适用场景 | 核心工具 | 优势 | 劣势 |
|---------|---------|---------|------|------|
| **镜像同步方案** | 需要完整官方包镜像 | pip2pi + Nginx | 包完整性好,支持所有官方包 | 存储空间需求大,同步耗时 |
| **私有仓库方案** | 内部包分发为主 | pypiserver | 轻量级,专注于私有包 | 不提供官方包镜像 |
| **企业级方案** | 大规模企业环境 | Nexus3 | 功能全面,支持多语言 | 配置复杂,资源消耗大 |
## 二、镜像同步方案搭建步骤
### 2.1 环境准备与依赖安装
```bash
# 安装Python3和pip
yum install -y python3 python3-pip
# 安装必要的工具
pip3 install pip2pi
# 创建仓库目录结构
mkdir -p /opt/pypi/{packages,simple}
```
### 2.2 包同步与索引创建
```python
#!/usr/bin/env python3
# 同步指定包到本地仓库
import os
# 定义需要同步的包列表
required_packages = [
"requests",
"numpy",
"pandas",
"flask",
"django"
]
# 逐个下载包并创建索引
for package in required_packages:
os.system(f"pip download {package} -d /opt/pypi/packages/")
print(f"已下载包: {package}")
# 创建索引文件
os.system("dir2pi /opt/pypi/packages/")
print("索引创建完成")
```
### 2.3 Nginx配置发布
```nginx
# /etc/nginx/conf.d/pypi.conf
server {
listen 80;
server_name pypi.internal.company.com;
location / {
root /opt/pypi;
autoindex on;
charset utf-8;
}
# 简单包索引位置
location /simple/ {
alias /opt/pypi/simple/;
autoindex on;
}
# 包文件位置
location /packages/ {
alias /opt/pypi/packages/;
autoindex on;
}
}
# 重启Nginx服务
systemctl restart nginx
```
## 三、pypiserver私有仓库方案
### 3.1 服务端部署
```bash
# 安装pypiserver
pip install pypiserver
# 创建包存储目录
mkdir -p /opt/pypiserver/packages
# 启动服务
pypi-server -p 8080 -P . -a . /opt/pypiserver/packages &
# 或使用守护进程方式
nohup pypi-server -p 8080 /opt/pypiserver/packages > /var/log/pypiserver.log 2>&1 &
```
### 3.2 客户端配置
```ini
# ~/.pip/pip.conf 或 /etc/pip.conf
[global]
index-url = http://pypi.internal.company.com:8080/simple
trusted-host = pypi.internal.company.com
timeout = 60
[install]
trusted-host = pypi.internal.company.com
```
### 3.3 包上传与管理
```python
#!/usr/bin/env python3
# 包上传脚本示例
import subprocess
import os
def upload_package(package_path, repository_url):
"""
上传Python包到私有仓库
"""
cmd = [
"twine", "upload",
"--repository-url", repository_url,
"--username", "admin",
"--password", "password",
package_path
]
try:
result = subprocess.run(cmd, check=True, capture_output=True, text=True)
print(f"包上传成功: {package_path}")
return True
except subprocess.CalledProcessError as e:
print(f"上传失败: {e}")
return False
# 使用示例
if __name__ == "__main__":
# 上传本地构建的包
upload_package(
"dist/mypackage-0.1.0.tar.gz",
"http://pypi.internal.company.com:8080"
)
```
## 四、Nexus3企业级方案
### 4.1 Docker部署Nexus3
```yaml
# docker-compose.yml
version: '3.8'
services:
nexus:
image: sonatype/nexus3:latest
container_name: nexus3
restart: unless-stopped
ports:
- "8081:8081"
volumes:
- nexus-data:/nexus-data
environment:
- INSTALL4J_ADD_VM_PARAMS=-Xms2703m -Xmx2703m -XX:MaxDirectMemorySize=2703m
volumes:
nexus-data:
```
### 4.2 PyPI代理仓库配置
```bash
# 启动Nexus服务后访问 http://your-server:8081
# 默认账号: admin 密码: admin123
# 创建Blob Store
curl -u admin:admin123 -X POST \
http://localhost:8081/service/rest/v1/blobstores/file \
-H 'Content-Type: application/json' \
-d '{"name": "pypi-blob", "path": "pypi-blob"}'
# 创建代理仓库
curl -u admin:admin123 -X POST \
http://localhost:8081/service/rest/v1/repositories/pypi/proxy \
-H 'Content-Type: application/json' \
-d '{
"name": "pypi-proxy",
"online": true,
"storage": {
"blobStoreName": "pypi-blob",
"strictContentTypeValidation": true
},
"proxy": {
"remoteUrl": "https://pypi.org/simple/",
"contentMaxAge": 1440,
"metadataMaxAge": 1440
},
"negativeCache": {
"enabled": true,
"timeToLive": 1440
},
"httpClient": {
"blocked": false,
"autoBlock": true
}
}'
```
### 4.3 客户端使用配置
```python
# 配置pip使用Nexus代理
"""
在客户端机器上创建pip配置文件:
Linux/Mac: ~/.pip/pip.conf
Windows: %APPDATA%\pip\pip.ini
"""
# pip.conf 内容
[global]
index-url = http://nexus-server:8081/repository/pypi-proxy/simple
trusted-host = nexus-server
timeout = 120
[install]
trusted-host = nexus-server
```
## 五、批量同步脚本示例
```python
#!/usr/bin/env python3
# 批量同步官方包到内网仓库
import requests
import subprocess
import json
from concurrent.futures import ThreadPoolExecutor
class PyPISyncManager:
def __init__(self, local_repo_path, sync_list_file):
self.local_repo = local_repo_path
self.sync_list = self.load_sync_list(sync_list_file)
def load_sync_list(self, file_path):
"""加载需要同步的包列表"""
with open(file_path, 'r') as f:
return [line.strip() for line in f if line.strip()]
def sync_package(self, package_name):
"""同步单个包"""
try:
# 下载包
cmd = [
"pip", "download",
package_name,
"-d", f"{self.local_repo}/packages",
"--no-deps"
]
result = subprocess.run(
cmd,
capture_output=True,
text=True,
timeout=300
)
if result.returncode == 0:
print(f"✅ 成功同步: {package_name}")
return True
else:
print(f"❌ 同步失败: {package_name} - {result.stderr}")
return False
except Exception as e:
print(f"❌ 同步异常: {package_name} - {str(e)}")
return False
def batch_sync(self, max_workers=5):
"""批量同步包"""
print(f"开始批量同步 {len(self.sync_list)} 个包...")
with ThreadPoolExecutor(max_workers=max_workers) as executor:
results = list(executor.map(self.sync_package, self.sync_list))
success_count = sum(results)
print(f"同步完成: 成功 {success_count}/{len(self.sync_list)}")
# 重新生成索引
self.regenerate_index()
def regenerate_index(self):
"""重新生成包索引"""
cmd = ["dir2pi", self.local_repo + "/packages"]
subprocess.run(cmd, check=True)
print("索引重新生成完成")
# 使用示例
if __name__ == "__main__":
sync_manager = PyPISyncManager(
"/opt/pypi",
"package_list.txt"
)
sync_manager.batch_sync()
```
## 六、安全配置与最佳实践
### 6.1 访问控制配置
```nginx
# Nginx访问控制配置
server {
listen 80;
server_name pypi.internal.company.com;
# 基础认证
auth_basic "PyPI Repository";
auth_basic_user_file /etc/nginx/.htpasswd;
# IP白名单
allow 192.168.1.0/24;
allow 10.0.0.0/8;
deny all;
location / {
root /opt/pypi;
autoindex on;
}
}
# 创建认证文件
htpasswd -c /etc/nginx/.htpasswd username
```
### 6.2 监控与维护脚本
```python
#!/usr/bin/env python3
# 仓库健康检查脚本
import os
import requests
import smtplib
from email.mime.text import MIMEText
class RepositoryMonitor:
def __init__(self, repo_url, alert_emails):
self.repo_url = repo_url
self.alert_emails = alert_emails
def check_availability(self):
"""检查仓库可用性"""
try:
response = requests.get(
f"{self.repo_url}/simple/",
timeout=10
)
return response.status_code == 200
except:
return False
def check_disk_space(self, path, threshold_gb=10):
"""检查磁盘空间"""
stat = os.statvfs(path)
free_gb = (stat.f_bavail * stat.f_frsize) / (1024**3)
return free_gb > threshold_gb
def send_alert(self, subject, message):
"""发送告警邮件"""
msg = MIMEText(message)
msg['Subject'] = subject
msg['From'] = 'pypi-monitor@company.com'
msg['To'] = ', '.join(self.alert_emails)
# 这里配置SMTP服务器
# with smtplib.SMTP('smtp.company.com') as server:
# server.send_message(msg)
print(f"告警: {subject}\n{message}")
def run_health_check(self):
"""执行健康检查"""
issues = []
if not self.check_availability():
issues.append("仓库服务不可用")
if not self.check_disk_space("/opt/pypi"):
issues.append("磁盘空间不足")
if issues:
self.send_alert(
"PyPI仓库健康检查告警",
"\n".join(issues)
)
else:
print("✅ 仓库状态正常")
# 使用示例
monitor = RepositoryMonitor(
"http://pypi.internal.company.com",
["admin@company.com"]
)
monitor.run_health_check()
```
## 七、客户端统一配置方案
### 7.1 自动化配置脚本
```bash
#!/bin/bash
# deploy_pip_config.sh - 自动化部署pip配置
REPO_SERVER="pypi.internal.company.com"
CONFIG_DIR="/etc/pip"
# 创建配置目录
mkdir -p $CONFIG_DIR
# 生成pip配置文件
cat > $CONFIG_DIR/pip.conf << EOF
[global]
index-url = http://$REPO_SERVER/simple
trusted-host = $REPO_SERVER
timeout = 120
[install]
trusted-host = $REPO_SERVER
trusted-host = pypi.org
trusted-host = files.pythonhosted.org
EOF
# 设置权限
chmod 644 $CONFIG_DIR/pip.conf
echo "Pip配置已部署到 $CONFIG_DIR/pip.conf"
```
### 7.2 容器环境配置
```dockerfile
# Dockerfile示例 - 配置内网pip源
FROM python:3.9-slim
# 配置内网pip源
RUN mkdir -p /root/.pip
COPY pip.conf /root/.pip/pip.conf
# 或者使用环境变量方式
# ENV PIP_INDEX_URL=http://pypi.internal.company.com/simple
# ENV PIP_TRUSTED_HOST=pypi.internal.company.com
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["python", "app.py"]
```
通过上述完整的搭建方案,企业可以根据自身需求选择适合的内网pip仓库方案,确保Python包管理的安全性、稳定性和高效性 [ref_1][ref_2][ref_3]。