Skip to content

Commit 247ba7d

Browse files
committed
新增建立私有 Python Package Registry 的實作筆記,涵蓋架構設計、設定步驟及常見問題解決方案
1 parent a8bf80b commit 247ba7d

File tree

1 file changed

+249
-0
lines changed

1 file changed

+249
-0
lines changed
Lines changed: 249 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,249 @@
1+
---
2+
title: " [實作筆記] 建立私有 Python Package Registry - 以 ONNX Runtime 為例"
3+
date: 2025/09/02 14:42:42
4+
tags:
5+
- 實作筆記
6+
---
7+
8+
## 前情提要
9+
10+
在開發 AI 應用時,我們遇到一些特殊的依賴管理需求,需要私有 Registry
11+
12+
在這個專案中,我們遇到了幾個挑戰:
13+
14+
1. **平台特化需求**:Jetson 平台需要特製的 `onnxruntime-gpu` 版本,PyPI 上沒有現成的
15+
2. **版本一致性**:確保所有環境(開發、測試、生產)使用完全相同的依賴版本
16+
3. **安全性考量**:避免依賴外部不穩定的來源,降低供應鏈攻擊風險
17+
4. **內部套件分發**:團隊開發的內部工具需要有管道分發
18+
19+
## 架構設計
20+
21+
整體架構分為三個層次:
22+
23+
```text
24+
┌───────────────────────┐
25+
│ GitLab CI/CD │ → 自動化構建與發布
26+
├───────────────────────┤
27+
│ Package Registry │ → 私有套件儲存
28+
├───────────────────────┤
29+
│ Project Dependencies │ → 專案依賴管理
30+
└───────────────────────┘
31+
```
32+
33+
## 實作步驟
34+
35+
### 設定 GitLab Package Registry
36+
37+
首先,在 GitLab 專案中啟用 Package Registry,並建立 Deploy Token:
38+
39+
在 GitLab 專案設定中建立 Deploy Token, Settings → Repository → Deploy Tokens
40+
41+
權限:read_package_registry, write_package_registry
42+
43+
記下 token ID 和 token 值,格式如下:
44+
45+
- Token ID: deploy-token-{ID}
46+
47+
- Token: {TOKEN}
48+
49+
### 取得 Project ID
50+
51+
有三種方式可以找到 GitLab Project ID:
52+
53+
從專案首頁:
54+
55+
進入你的 GitLab 專案首頁
56+
Project ID 會顯示在專案名稱下方
57+
例如:Project ID: 12345678
58+
59+
從專案設定頁面:
60+
61+
進入 Settings → General
62+
在最上方的 "General project settings" 區塊
63+
可以看到 Project ID
64+
65+
從 GitLab API:
66+
67+
如果你在 CI/CD pipeline 中,可以直接使用環境變數 $CI_PROJECT_ID
68+
這個變數會自動帶入當前專案的 ID
69+
70+
### 配置專案的依賴管理
71+
72+
`pyproject.toml` 中設定私有 registry:
73+
74+
```toml
75+
# 定義私有 index
76+
[[tool.uv.index]]
77+
name = "onnx"
78+
url = "https://gitlab+deploy-token-{TOKEN_ID}:{TOKEN}@gitlab.com/api/v4/projects/{PROJECT_ID}/packages/pypi/simple"
79+
default = false
80+
81+
# 指定套件來源
82+
[tool.uv.sources]
83+
onnxruntime-gpu = { index = "onnx" }
84+
85+
# 多平台依賴策略
86+
dependencies = [
87+
# macOS ARM64 使用 CPU 版本
88+
"onnxruntime==1.19.0; sys_platform == 'darwin' and platform_machine == 'arm64'",
89+
# Jetson 使用私有倉庫的 GPU 版本
90+
"onnxruntime-gpu; sys_platform == 'linux' and platform_machine == 'aarch64'",
91+
]
92+
```
93+
94+
這裡的關鍵是使用條件依賴,根據不同平台安裝不同版本的套件。
95+
96+
### 3. 開發者使用私有 Registry
97+
98+
根據專案的安全策略,RD 有幾種方式存取私有 registry:
99+
100+
#### 選項 1:Token 內嵌在 pyproject.toml(簡單但不安全)
101+
102+
如果 `pyproject.toml` 中已經包含完整的認證 URL:
103+
104+
```bash
105+
# 直接安裝依賴
106+
uv sync
107+
108+
# 或使用 pip
109+
pip install -e .
110+
```
111+
112+
#### 選項 2:使用環境變數(推薦)
113+
114+
`pyproject.toml` 中使用佔位符:
115+
116+
```toml
117+
url = "https://deploy-token-{TOKEN_ID}:${GITLAB_TOKEN}@gitlab.com/api/v4/projects/{PROJECT_ID}/packages/pypi/simple"
118+
```
119+
120+
RD 需要設定環境變數:
121+
122+
```bash
123+
export GITLAB_TOKEN=your_deploy_token
124+
uv sync
125+
```
126+
127+
#### 選項 3:使用認證檔案
128+
129+
設定 pip 或 uv 的認證檔案:
130+
131+
```bash
132+
# 建立 pip 配置
133+
cat > ~/.pip/pip.conf <<EOF
134+
[global]
135+
extra-index-url = https://deploy-token-{TOKEN_ID}:{TOKEN}@gitlab.com/api/v4/projects/{PROJECT_ID}/packages/pypi/simple
136+
EOF
137+
```
138+
139+
#### 選項 4:企業內網存取
140+
141+
如果使用企業內網或 VPN:
142+
143+
```bash
144+
# 連接 VPN 後直接使用
145+
uv sync
146+
```
147+
148+
### 4. CI/CD 自動化發布
149+
150+
設定 GitLab CI 自動構建並推送套件到 registry:
151+
152+
```yaml
153+
# .gitlab-ci.yml
154+
variables:
155+
REGISTRY_PATH: registry.gitlab.com/$GROUP_PATH/$PROJECT_NAME
156+
157+
stages:
158+
- build
159+
- publish
160+
161+
build-package:
162+
stage: build
163+
script:
164+
# 構建 Python 套件
165+
- pip install build
166+
- python -m build
167+
artifacts:
168+
paths:
169+
- dist/
170+
171+
publish-to-registry:
172+
stage: publish
173+
dependencies:
174+
- build-package
175+
script:
176+
# 設定認證
177+
- pip install twine
178+
- |
179+
cat > ~/.pypirc <<EOF
180+
[distutils]
181+
index-servers = gitlab
182+
183+
[gitlab]
184+
repository = https://gitlab.com/api/v4/projects/${CI_PROJECT_ID}/packages/pypi
185+
username = gitlab-ci-token
186+
password = ${CI_JOB_TOKEN}
187+
EOF
188+
189+
# 上傳到 GitLab Package Registry
190+
- python -m twine upload --repository gitlab dist/*
191+
only:
192+
- main
193+
```
194+
195+
### 6. Docker 映像支援多架構
196+
197+
為了支援不同的硬體平台,使用 buildx 構建多架構映像:
198+
199+
```yaml
200+
build-multi-arch:
201+
stage: build
202+
script:
203+
# 設定 buildx
204+
- docker buildx create --use
205+
206+
# 構建並推送多架構映像
207+
- |
208+
docker buildx build \
209+
--platform linux/amd64,linux/arm64 \
210+
-t $REGISTRY_PATH:$NEW_TAG \
211+
--push .
212+
```
213+
214+
## 常見問題與解決方案
215+
216+
### Deploy Token 權限不足?
217+
218+
確保 Deploy Token 有 `read_package_registry` 和 `write_package_registry` 權限。
219+
220+
### 套件版本衝突?
221+
222+
使用 `uv` 的 resolution markers 功能,明確指定版本解析策略。
223+
224+
### 多架構構建失敗?
225+
226+
檢查 Docker buildx 是否正確安裝,並確認基礎映像支援目標架構。
227+
228+
### Registry URL 格式錯誤?
229+
230+
GitLab PyPI registry URL 格式為:
231+
232+
```
233+
https://gitlab.com/api/v4/projects/{PROJECT_ID}/packages/pypi/simple
234+
```
235+
236+
注意將 `{PROJECT_ID}` 替換為實際的專案 ID。
237+
238+
## 小結
239+
240+
透過建立私有 Package Registry,我們成功解決了:
241+
242+
- **特製版本管理**:Jetson 平台的特殊 ONNX Runtime 版本需求
243+
- **依賴一致性**:所有環境使用相同版本的套件
244+
- **安全性提升**:減少對外部來源的依賴
245+
- **自動化流程**:CI/CD 自動構建並發布套件
246+
247+
這個架構不僅適用於 ONNX Runtime,也可以擴展到其他需要特殊管理的依賴套件。
248+
249+
(fin)

0 commit comments

Comments
 (0)