自建 PyPI / Conda 本地緩存或鏡像源
Pip 和 Conda 是 Python 的兩大軟件包管理工具,它們的官方源在國內(nèi)訪問困難,下載速度非常慢。一般情況下我們使用的都是國內(nèi)的鏡像源,例如清華大學(xué)的 TUNA 鏡像站、阿里云的鏡像站。
但是有些軟件包體積非常大,安裝的時(shí)候從鏡像站下載下來仍然需要等待很長(zhǎng)時(shí)間,如果正巧遇到鏡像站負(fù)載高峰導(dǎo)致下載速度緩慢,那更是雪上加霜。
為了防止配環(huán)境的時(shí)候軟件包下載等待時(shí)間過長(zhǎng),一個(gè)可行的方法就是搭建一個(gè)本地鏡像源,在下載的時(shí)候直接從本地鏡像源下載,速度能夠達(dá)到內(nèi)網(wǎng)帶寬。如果是千兆內(nèi)網(wǎng),那么理論可以達(dá)到 125MB/s,這個(gè)速度即使是好幾個(gè) GB 的軟件包,也能在半分鐘內(nèi)裝好。
本文轉(zhuǎn)自我的個(gè)人博客
原文鏈接:https://www.zouht.com/3310.html
本文使用:CC BY-NC-SA 4.0 許可
1. 前言
首先我們需要知道緩存源和鏡像源的區(qū)別:
緩存源:初始狀態(tài)為空。下載請(qǐng)求的軟件包沒有緩存,則回源到設(shè)置的上游鏡像源,然后該軟件包會(huì)被緩存。如果請(qǐng)求的軟件包已經(jīng)被緩存,則直接從本地緩存返回用戶。
下載速度:第一次速度 = 通過外網(wǎng)從上游鏡像源下載的速度;之后的速度 = 內(nèi)網(wǎng)帶寬速度。
磁盤空間:少。初始時(shí)只保存了軟件包索引,隨著使用過程,軟件包被緩存,磁盤占用逐漸變大。
鏡像源:初始狀態(tài)含有所有軟件包,并且定時(shí)與上游鏡像源同步。當(dāng)下載請(qǐng)求到來時(shí)直接返回本地文件。
下載速度:內(nèi)網(wǎng)帶寬速度,即使公網(wǎng)斷了也能正常下載。
磁盤空間:極大。完整的鏡像都是 10TB+ 級(jí)別的,當(dāng)然我們可以選擇鏡像一個(gè)子集。
通過上面的對(duì)比,可以發(fā)現(xiàn)這兩種方案各有優(yōu)劣。緩存源類似 CDN 緩存,鏡像源則相當(dāng)于全部復(fù)制。
這篇文章選擇的方案是:
PyPI:使用 devpi (+ Nginx) 搭建緩存源
Conda:使用 Python + Nginx 搭建鏡像源
PyPI 選擇搭建緩存源的原因是 Pypi 的完整庫體積過大(目前已經(jīng)有 16TB,詳見?https://pypi.org/stats/),全部鏡像一遍成本過高,且平時(shí)根本用不到所有軟件包,所以選擇搭建緩存源。如果你恰好財(cái)力雄厚,也可以選擇搭建鏡像源,可使用?bandersnatch?進(jìn)行同步(TUNA 就是用的這個(gè)程序).
而 Conda 選擇搭建鏡像源的原因是沒有好用的緩存源程序,并且 Conda 的軟件包數(shù)目比 Pypi 少很多,而且如果只下載 Windows 和 Linux 版本的軟件包,搭建鏡像源所需儲(chǔ)存空間也能夠接受(~800GB). 當(dāng)然如果如果要搭建完整鏡像,大小仍然是很夸張的 11TB.
2. 使用 devpi 搭建 PyPI 緩存源
快速配置
devpi 本身是一個(gè) Python 軟件包,可通過 pip 下載:pip install devpi
安裝好后,首先需要初始化。使用?devpi-init --serverdir=[PATH]
?進(jìn)行初始化,其中?[PATH]
?代表程序的工作目錄,配置文件和緩存都儲(chǔ)存在這個(gè)目錄下,因此該目錄的儲(chǔ)存空間一定要充足。如果不指定這個(gè)參數(shù),則工作目錄默認(rèn)在用戶目錄下:~/.devpi/server
初始化后,就可以啟動(dòng)服務(wù)器了。使用?devpi-server --host=[HOST] --port=[PORT] --serverdir=[PATH]
?啟動(dòng)服務(wù)器,其中?[HOST]
?為監(jiān)聽的地址,填寫 127.0.0.1 則只有本機(jī)能訪問,填寫 0.0.0.0 則任何主機(jī)都能訪問,[PORT]
?為監(jiān)聽的端口,[PATH]
?為剛才初始化選擇的工作目錄。
此時(shí)緩存源就已經(jīng)正常運(yùn)行了,不過 devpi 默認(rèn)的上游鏡像源是官方源,回源的時(shí)候會(huì)很慢,我們可以改成國內(nèi)鏡像。首先使用?devpi use http://[HOST]:[PORT]/root/pypi
?選擇我們剛才搭建的鏡像源(此時(shí)不要關(guān)閉 devpi-server),然后使用?devpi login root
?登陸 root 賬號(hào),默認(rèn)密碼為空直接回車即可。
然后選擇使用以下命令切換上游鏡像:
配置 pip 下載源
如果是臨時(shí)使用的話,在 pip 安裝時(shí)指定 -i 參數(shù)填寫下載源即可:
pip install -i [HOST]:[PORT] some-package
pip 需要手動(dòng)信任非 https 的源,因此需要額外加?--trust-host
?參數(shù):
pip install -i http://[HOST]:[PORT]/root/pypi --trust-host [HOST]:[PORT] some-package
如果需要將其設(shè)為默認(rèn),則需要修改 pip 設(shè)置:
pip config set global.index-url http://[HOST]:[PORT]/root/pypi
pip 需要手動(dòng)信任非 https 的源,因此需要額外修改:
pip config set global.trusted-host [HOST]:[PORT]
高級(jí)配置
上面的快速配置只是提供了基本的服務(wù),如果你是安裝在主力機(jī)上臨時(shí)使用,這樣就已經(jīng)足夠了。如果你想配置到服務(wù)器上永久使用,則需要一些高級(jí)配置。下面的操作均使用 Linux 系統(tǒng)完成。
首先生成配置文件,使用?devpi-gen-config --host=[HOST] --port=[PORT] --serverdir=[PATH]
,配置文件就會(huì)生成到當(dāng)前目錄的?gen-config
?文件夾下。
我們本篇教程用到的是:
devpi.service:systemctl 服務(wù)配置文件
nginx-devpi.conf:Nginx 站點(diǎn)配置文件
首先使用 systemctl 實(shí)現(xiàn)服務(wù)自啟,將配置文件拷貝到服務(wù)目錄:cp gen-config/devpi.service /etc/systemd/system/
然后啟用服務(wù):systemctl enable devpi.service
然后啟動(dòng)服務(wù):systemctl start devpi.service
查看服務(wù)狀態(tài):systemctl status devpi.service
如果顯示綠色則說明服務(wù)正常啟動(dòng)了。
然后使用 Nginx 實(shí)現(xiàn)反向代理,首先要保證服務(wù)器裝有 Nginx:apt install nginx
然后將配置文件拷貝到 Nginx 配置目錄:cp gen-config/nginx-devpi.conf /etc/nginx/sites-available
然后鏈接到啟動(dòng)的網(wǎng)站目錄:ln -s /etc/nginx/sites-available/nginx-devpi.conf /etc/nginx/sites-enabled/nginx-devpi.conf
最后重載配置文件:systemctl reload nginx
3. 使用 Python + Nginx 搭建 Conda 鏡像源
鏡像同步
同步上游鏡像源使用的是 TUNA 提供的 Python 腳本,開源在 GitHub 上:https://github.com/tuna/tunasync-scripts/blob/master/anaconda.py
該腳本默認(rèn)上游源為官方源,同步規(guī)模為完整同步 (11TB),我將這個(gè)腳本進(jìn)行了調(diào)整,具體調(diào)整和對(duì)應(yīng)代碼行號(hào)如下:
(19~29) 上游源調(diào)整為 TUNA 清華源,加速同步
(34~36) 軟件包只同步 Linux 64 位、Windows 64 位和通用三種系統(tǒng)架構(gòu),減小鏡像體積。大家可以根據(jù)自己的設(shè)備情況進(jìn)行調(diào)整。
(38~40, 235~236) Conda 安裝包只同步 Linux 64 位、Windows 64 位兩種,減小鏡像體積。
(42~44) 刪除全部額外 Conda 頻道,減小鏡像體積。如果大家需要用到 conda-forge 頻道,可以把注釋去掉。如果要用到其他頻道,可以去 GitHub 原版腳本查找。
(69, 80) 哈希校驗(yàn)全部跳過,直接返回 True,加快同步過程。如果大家想要啟動(dòng)校驗(yàn),則把這兩行修改恢復(fù)即可。
(223~224) 每次同步都完整檢查安裝包。腳本默認(rèn)設(shè)置的是每次同步 10% 的幾率進(jìn)行完整同步,若不是完整同步,則腳本如果發(fā)現(xiàn)最新版已經(jīng)同步了之后就會(huì)直接跳過,不再檢查舊版。
如果使用我這個(gè)腳本進(jìn)行同步的話,鏡像大小大約為 800GB. 大家可以根據(jù)自己的實(shí)際情況進(jìn)行調(diào)整。不過有幾點(diǎn)需要注意:
由于 TUNA 源的安裝包列表格式和官方源不同,所以如果上游源指定為 TUNA 源時(shí),安裝包 (archive 和 miniconda) 無法正常同步。如果想要同步安裝包,需要把上游源改回官方源。
Python 元組不能只有一個(gè)元素,
("main")
?這種元組會(huì)被直接視為字符串,會(huì)導(dǎo)致腳本異常。如果你修改腳本時(shí)將一些元組刪的只剩一個(gè)了,記得保留一個(gè)逗號(hào),變成?("main",)
?這樣腳本就能正常運(yùn)行了。
修改版的腳本如下:
如果要使用該腳本,首先要安裝 Python,然后再安裝對(duì)應(yīng)的 Python 軟件包。啟動(dòng)指令為:
python anaconda.py --working-dir=[PATH]
其中?[PATH]
?為儲(chǔ)存鏡像的目錄,需要保證這個(gè)目錄空間充足,建議至少留 500GB 空間。我宿舍的網(wǎng)速限制為 50Mbps,同步 800GB 花了兩天。
運(yùn)行 HTTP 服務(wù)
同步好后,就可以配置 Nginx HTTP 服務(wù)器了,當(dāng)然如果懶得用 Nginx,也可以直接用 Python,性能差一點(diǎn)罷了:python -m http.server
Nginx 配置文件中,配置好 root 目錄就行了。同時(shí)也可以打開 autoindex 功能,這樣訪問的時(shí)候就能列出所有內(nèi)容了。配置文件的片段如下,記得把?[PATH]
?替換為自己的目錄:
最后,還可以用 crontab 實(shí)現(xiàn)定時(shí)任務(wù),定時(shí)進(jìn)行同步,使用?crontab -e
?編輯任務(wù),然后添加一行:
前面的五位為定時(shí)時(shí)間,上面設(shè)置的是每天早上 9 點(diǎn),后面是定時(shí)運(yùn)行的指令,記得自己調(diào)整目錄。
配置 conda 鏡像源
conda 的配置文件在?~/.condarc
,打開這個(gè)配置文件,設(shè)置:
default_channels 是同步的默認(rèn)源,將其替換為我們本地鏡像的地址。custom_channels 是額外的頻道,我搭建的時(shí)候沒有同步額外頻道,所以這里我填寫的是清華 TUNA 源。如果大家同步了額外頻道,則將其對(duì)應(yīng)的修改為本地鏡像的地址。