Python 項目的部署,目前互聯網公司有哪些成熟的方案?

想做一些Python項目的自動上線部署工具,但是Python的包依賴,不能像Java那樣把具體的jar打包部署時直接解壓再改個配置文件就好,必須在部署之前要一個個安裝所依賴的模塊,這樣一個是效率低不說,而且在安裝的過程中出錯的幾率也比較高,

想知道目前各互聯網公司都是如何做的,有哪些成熟的方案 ?


&> Python 的包依賴,不能像 Java 那樣把具體的 jar 打包部署時直接解壓

在一定程度上這是可以做到的。 類似 Java 的 jar 包,Python 長久以來存在一種 egg 包 (其實 wheel 包也可以,但我後面介紹的工具不支持), 只要放在 sys.path 中就可直接被 import。

比如我的這個項目 GitHub - youngking/buildout-package: My Custom buildout script

參考下 bin/buildout 的寫法, 代碼拖到哪裡都可以直接在項目下運行 bin/buildout。

使用 zc.buildout 這個工具能夠自動做我上面那個項目的封裝。這個工具可以把項目所有依賴的包 download 下來,並打成 egg 包。默認egg 包放在你的項目下的 eggs 目錄, 同時會生成一個 bin 目錄, 裡面放著根據當前項目的 setup.py 定義的 entrypoint 生成的各種命令, buildout 會修改命令腳本的 sys.path, 把依賴的egg 都加進去。

假如你的項目之前是這樣的:

project/
setup.py
src/
tests/
.....

使用 zc.buildout 構建後會是這個樣子:

project/
bin/
buildout.cfg
eggs/
setup.py
src/
tests/
...

把整個目錄拷貝到環境一樣的其他機器上的相同位置,就能直接運行。由於生成的命令是絕對路徑,所以需要約定路徑相同。也可以在 buildout 中啟用 relative-paths=true 這個配置,結合 zc.recipe.egg 這個 recipe 可以讓 bin 目錄下的腳本使用相對路徑來修改 sys.path。 最後腳本的樣子就和我倉庫裡面類似了。

在知乎我們的傳統部署方式是在 ci 的機器上構建時使用 buildout 拉下所有的依賴包,然後項目測試通過後整體打成一個 tar 包傳到 s3上。要部署的目標機部署時從 s3 上把這個 tar 包下載下來,解壓到相應的位置後即可被運行。

此外 twitter 有一個神器 pantsbuild/pex: A library and tool for gene... , 也能把整個應用及其依賴打包成一個可執行的 Python 虛擬環境。


考慮下將依賴打成wheel包來離線安裝?


  • Docker 不是銀彈。開發偷懶了,運維、平台就要還債。如果想在生產環境使用它,你的團隊需要有成熟的運維,和有追蹤上游 Bug 的能力的工程師,以及能從業務需求中抽身出來填技術坑的條件。所以,小公司小團隊請慎用。
  • 複製 virtualenv 部署可行,但移植性不好。一來 virtualenv 不允許絕對路徑變動,二來 virtualenv 中一些已經裝上的包可能依賴系統的動態庫(如 OpenSSL),直接複製可能遇到 ABI 兼容問題。
  • 僅僅對於 Python 項目部署來說,利用 setup.py 打包是個不錯的選擇。一般 Web 應用中只有 requirements.txt 沒有 setup.py,那麼可以寫一個僅用於打包的 setup.py,其中 install_require 部分讀入 requirements.txt 的數據

setup.py 打包 Web 應用的話,需要一個 CI 伺服器,Travis CI、GitLab CI、Jenkins 等均可。setup.py 默認不支持滾動發行,所以讀入 JOB_IDBUILD_ID 之類的 CI 環境變數作為版本號,或者用當前日期時間生成一個。CI 服務中,可以設置主倉庫 master 通過測試以後,自動向內部的 PyPI 發版本(如果用 Jenkins 也可以用 Jenkins 自帶的靜態文件服務)。在部署時再在內部 PyPI 中選擇一個版本,pip install 到生產環境節點上。

基於 setup.py,可以通過 http://MANIFEST.in 的定義,將資源文件也打到發行包中,例如 gulp 編譯產生的前端靜態文件。而且如果有其他項目(比如獨立的管理員後台)依賴當前應用,做服務又太麻煩時,可以直接向內部 PyPI 援引當前應用作為依賴。這樣可以諸如避免手動修改 sys.path 那樣的高度環境綁定且不可移植的 hack。

我在我現在就職的公司已經嘗試推行了這種方法,目前看來沒有遇到什麼坑的問題。而且打成 wheel 包之後,部署速度也變快了(省下了部署時編譯附加資源的時間)。這裡貼出我們在用的配置,供參考: setup.py - GitHub

其他的一些信息:

  • 如果需要搭建內網 PyPI,推薦 devpi
  • setup.pyclassifiers 一節請記得加入 Private :: Do Not Upload,公共 PyPI 會拒絕收錄有這個標記的包。這樣可以防止萌萌噠隊友手滑把公司代碼傳到公網 PyPI。
  • 如果把項目的其他依賴也打成 wheel 發布到內網 PyPI,可以省下很多構建編譯的時間。但是要當心,wheel 格式目前無法做到 ABI 兼容(這也是公共 PyPI 暫時只允許針對 Windows 和 OS X 發布 wheel 的原因),請盡量保持打包環境(即 CI 伺服器)所用的 Linux 發行版和生產環境一致
  • 配置 CI 時不應該將內網 PyPI 的登錄密碼提交到版本庫。絕大多數 CI 系統都支持私密環境變數
  • 不管用不用 setup.py 來做打包,Python 項目的生產環境部署都應該使用 virtualenv,即使一台機器只部署一個應用。virtualenv 至少能將項目依賴和 Linux 發行版的依賴隔離開。


瀏覽了以上所有人的答案,結合我平常在項目中的實際經驗,談談我們團隊的Python部署與發布流程。

目前很多公司還是用著石器時代的部署方式,怎麼做呢?

1. 本地寫代碼,可能還沒有virtualenv環境,是的其實我的老東家就是這樣的。

2. 寫一個腳本,安裝需要的依賴到系統global環境,比如說 MySQLdb,
可能還要用apt-get 或者 yum 安裝 python-dev 等等系統依賴,然後用pip 安裝Python依賴。

3. 提交到svn/git,然後在測試機器上拉代碼下來,運行腳本安裝完依賴後,
如果是一個web項目,那麼可能會直接 python web.py 8080 測試一下會不會報錯,
測試完幾個介面發現沒問題,關掉測試機器。

4. 在生產環境把代碼拉下來,或者通過部署系統,這裡的部署系統一般是一個web頁面,
能夠將svn/git 上的代碼打包後執行某一個腳本,來完成相應的部署,
也有可能是直接在機器上執行:
nohup python /path/to/python/main.py 21 &> /dev/null
就啟動來這個進程,然後自己可能還有一些業務監控來定時的監控這個腳本的存活狀態。

5. 這裡可能nginx已經配置好,你發布的是一個Django應用,那麼打開瀏覽器,
查看網頁無誤。

ok,大功告成,我已經是一位合格的工程師了,我所理解的Python發布或者所有的發布不都是這樣么,大家都是這樣的

如果你躺槍了,很好,我喜歡。

讓我們看看這裡的步驟缺少什麼,我不僅僅從發布部署來說,我們談談一個理想的開發測試部署流程應該是怎樣的。

1. 你應該有一個與線上環境一模一樣的測試/開發機器,這裡說的是系統環境而不是物理環境,比如說內核版本,Python版本,libc 版本,gcc 版本,shell 的環境等等都應該跟線上環境一樣,這是保證代碼質量的第一關,或許不應該叫做代碼質量而是工程質量。有人可能會用eclipse或者其他的云云開發IDE,OK,沒問題,保證系統是一樣的,這裡有點難。

2. 你應該有一個virtualenv環境,因為你的開發機器可能有多個項目,而且可能因為有些依賴版本問題,導致你發現不同的項目可能對同一個模塊有不同版本的依賴,那麼請你準備一個virtualenv環境,這是Python開發人員必備的。

3. 你應該把代碼提交到git, 但是提交之前,你應該運行一般單元測試,單元測試包含兩個部分,一是對整個項目里的所有代碼有一個代碼靜態檢查,例如pylint和pep8,第二部分是自動運行你的測試用例,因為你的一個小改動可能會影響到其他模塊,而這一點你開發的時候沒有意識到或者說你影響的模塊不是你寫的,這一點會讓你寫的代碼更健壯,同時你更有信心對現有代碼做新需求開發或者變動,這裡,你可以把你的測試用例啟動腳本活著命令加到git hook,這樣每次commit的時候都會啟動測試程序。

4. OK,保證測試用例通過後,你應該對這次寫的代碼很有信心了,那接下來就是把代碼發布到測試環境。怎麼做呢?

一個起碼看起來合格的Python項目,大體上代碼構建的目錄應該是下面這樣的,請參考《以正確的方式開源Python項目》 http://www.oschina.net/translate/open-sourcing-a-python-project-the-right-way

所有的代碼文件都在pro中,其他都是項目發佈於部署使用到的

-rwxr-xr-x 8 root root 4096 Sep 16 22:06 .git/
-rw-r--r-- 1 root root 434 Aug 10 16:00 .gitignore
-rw-r--r-- 1 root root 166 Jul 26 11:49 AUTHORS.md
-rw-r--r-- 1 root root 149 Aug 10 16:49 AUTHORS.rst
-rw-r--r-- 1 root root 0 Aug 10 16:49 CONTRIBUTING.rst
-rw-r--r-- 1 root root 245 Jul 26 11:59 HISTORY.md
-rw-r--r-- 1 root root 100 Aug 10 16:49 HISTORY.rst
-rw-r--r-- 1 root root 1453 Aug 10 16:49 LICENSE
-rw-r--r-- 1 root root 221 Aug 10 16:49 MANIFEST.in
-rw-r--r-- 1 root root 2964 Sep 12 11:19 Makefile
-rw-r--r-- 1 root root 239 Jul 26 11:49 README.md
-rw-r--r-- 1 root root 161 Aug 10 16:49 README.rst
drwxr-xr-x 2 root root 4096 Sep 16 22:06 conf/
drwxr-xr-x 2 root root 4096 Jul 26 11:59 deb-scripts/
drwxr-xr-x 2 root root 4096 Aug 23 15:52 doc/
drwxr-xr-x 8 root root 4096 Jan 16 13:12 pro/
-rw-r--r-- 1 root root 67 Aug 10 16:49 requirements-dev.txt
-rw-r--r-- 1 root root 284 Sep 2 15:34 requirements.txt
-rw-r--r-- 1 root root 22 Aug 10 16:49 setup.cfg
-rwxr-xr-x 1 root root 1406 Aug 10 16:49 setup.py*
drwxr-xr-x 4 root root 4096 Sep 2 17:30 utils/

我來解釋一下這裡的幾個主要文件的作用. 這裡的目錄結構可能也跟我們團隊的命名習慣有關.

conf/
conf/api.conf // 項目配置
conf/logrotate.conf // 日誌輪轉配置
conf/uwsgi.ini // uwsgi 配置
conf/pro.upstart // upstart 文件
conf/paste.ini // paste 是用來部署uwsgi的一個中間件
conf/pro.cron // 這裡是crontab配置
conf/pro // 其他配置,可能是允許執行的sudo命令等

deb-scripts/ 包含三個文件,這裡我們說debian系統打包,Redhat 打 rpm 也同理。

eb-scripts/before-remove.sh // 卸載前執行的腳本
deb-scripts/before-install.sh // 安裝前執行的腳本
deb-scripts/after-install.sh // 安裝後執行的腳本

doc/ 應該是項目的文檔,這裡推薦用sphinx 生成文檔或者你自己寫markdown也可以。

utils/ 下面包含了你可能需要用到的啟動依賴,但是又不想每次都遠程下載,且不是Python本身的依賴而是環境依賴,好吧,我們在utils下面放了一個virtualenv,執行virtualenv 就可以在本地生成一個virtualenv 環境了, 還有打包deb的腳本

Makefile 文件包含了很多命令,比如:

make test // 執行單元測試和靜態檢查
make lint // 執行 pylint
make pep // 執行pep8 檢查

一系列你經常用到的功能,都可以放到Makefile

2. 你應該把你的代碼打成一個安裝包,而不是一個壓縮包,因為你要發布的是一個服務而不是一個模塊,那麼請你打成deb或者rpm包。

讓我們看下打包代碼:

#!/bin/sh
set -e

... // 省略了變數部分

if [ ! -d wheelhouse ]; then
make wheel
fi

fpm -t deb -s dir -n "$PKG_NAME" -v "$VERSION" --prefix "$DEST_DIR" -f
--depends make
-x *__pycache__
-x *.pyc
-x *.pyo
-x *.deb
--before-install deb-scripts/before-install.sh
--after-install deb-scripts/after-install.sh
--before-remove deb-scripts/before-remove.sh
Makefile HISTORY.rst LICENSE AUTHORS.rst CONTRIBUTING.rst setup.cfg
MANIFEST.in README.rst setup.py utils requirements-dev.txt requirements.txt wheelhouse conf
$PYTHON_MODULES

一目了然,我們會把依賴打到 wheelhouse 裡面,然後把 wheelhouse 一同打包到 deb 包,這裡使用了 fpm 這個打包工具,需要安裝ruby gem 來安裝。

然後在你的 make install 命令可以包含下面這個:

pip install --use-wheel --no-index --find-links=wheelhouse -r requirement.txt

在你的 deb-scirpt/after-install.sh 裡面,這個腳本會在deb包安裝完成後執行,你應該在這裡完成你的環境依賴安裝還有你配置文件的載入,crontab的配置等,一個簡單的腳本應該像下面這樣:

#!/bin/sh
set -e

PREFIX=${PREFIX:-/opt/pro}
REPODIR=${REPODIR:-/data2/pro}
LOGDIR=${LOGDIR:-/data2/log/pro}
IMAGE_CACHE=${IMAGE_CACHE:-/data2/image/cache}
RUN_AS_USER=www-data

mkdir -p $REPODIR
mkdir -p $LOGDIR
mkdir -p $IMAGE_CACHE

chown -R "$RUN_AS_USER":"$RUN_AS_USER" $REPODIR
chown -R "$RUN_AS_USER":"$RUN_AS_USER" $LOGDIR
chown -R "$RUN_AS_USER":"$RUN_AS_USER" $IMAGE_CACHE

cd "$PREFIX"
# this project does not require install.
# make bootstrap install
make bootstrap
# install crontab, upstart job, logrotate config etc
install conf/pro.upstart /etc/init/pro.conf
install conf/logrotate.conf /etc/logrotate.d/pro
install -o root -m 0440 conf/pro /etc/sudoers.d/pro
install -o root -m 0644 conf/pro.cron /etc/cron.d/pro

start pro || true

3. 最後一步就是 start pro

這裡使用upstart啟動你的應用,你應該把你的應用交給系統而不是你自己

所以在 after-install 中,你需要把pro.conf這個文件安裝到 upstart 目錄.

4. 以上的所有步驟,還在你的本地,你需要做的是把代碼發布到生產環境。這裡你需要把你的deb包上傳到私有apt源,然後就是發布到正式環境了。

5. 發布有幾種方式:

1. 在機器上直接執行 apt-get install pro(不推薦)
2. 利用fabric執行遠程命令發布(次不推薦)
3. 利用puppet發布(推薦)

前兩者無需多說,利用puppet發布,可以使你的發布更佳規範,同時也可以對配置做更規範的管理,一些系統依賴,不是Python的而是系統本身的,比如有時候出現libpcre 這樣的二進位系統依賴的時候,你應該利用puppet安裝這些依賴,而不是手動去執行安裝, 具體的 puppet 相關就不細說了。

OK,以上是個人比較推薦的Python流程,有錯誤請指正。


Fabric+VirtualENV+Pip+Pypi+Docker

Fabric, Ansible, Salt 做自動化部署

VirtualENV+Pip+requirements.txt + Pypi 或Docker 做項目環境管理

Nginx+uwsgi 做web服務


沒人提到 zc.buildout 么, 知乎正在用呀。


@松鼠奧利奧的答案已經很完全了。貌似都在說docker,這裡我也說說docker的情況吧,畢竟我司也是重度docker依賴。

首先就回答一下 @alexsunmiu的那些疑問,顯然這位老兄用docker的姿勢不對:

1. Docker這個玩意,有容器和鏡像兩個主要的概念,擔負的職責不同。鏡像負責運行環境的包裝,容器則是運行時的包裝。至於提到的主流老操作系統,這個屬於具體的業務依賴,沒法使用Docker那也是沒法的事情,但是請不要擅自斷言那些老的系統是主流,每個廠都不一樣的。

2. 容器移植打包其實是很方便的,你看到的容量大,只是表面的東西。Docker底層設計是高度復用的。一個鏡像是很多個層疊在一起的,比如你有一個docker鏡像,裡面是ubuntu+python,另一個是ubuntu+java,如果兩者的ubuntu版本一樣,那麼這部分的layer就是復用的。如果你之前已經pull過這個對應的ubuntu的鏡像,那麼這部分是不會重複下載的,只會下載對應的python和java的部分。

3. Docker通過cgroup隔離,安全性雖然沒有內核級別隔離的vm那麼高,但是控制好許可權,也是沒那麼容易淪陷的。

4.你apt要那麼久,是因為你沒有替換原始ubuntu鏡像里的sources.list,自然要被偉大的GFW制裁一番。事實上我國國情決定了無論使用啥外來工具,都得先改造一番。所以凡事用docker的廠子,都會先搞一個私有的registry和官方鏡像,然後再依據廠內的環境構建幾個基礎的docker鏡像。後面所有發布的app都是基於這些基礎鏡像來做。

5. Dockerfile的設計又不是給你做shell用的,這玩意是用來定義docker鏡像構建信息的,你有複雜的構建邏輯,一樣可以包裝到專門的腳本里,然後ADD進去運行不就完事么。

運維關注Docker的地方,主要在於穩定性,監控,日誌這幾個傳統方面。這些跟運維的KPI是掛鉤的。因為這東西還很新,而且特性還在慢慢增加,隱含的bug還是不少的,只不過只有在有足夠量,以及特定的一些場景(最常見的就是網路部分和日誌部分)才會出現。不是每個問題都能用自己熟悉的方式繞過去的。所以當碰到這些問題的時候,組裡有能追蹤bug的人才,甚至有能直接改代碼的人才會顯得很重要,因為這才能保證問題是可控的,否則哪天出問題了大家都搞不定,輕則年終獎完蛋,重則卷鋪子走人了。

=== update: 2016-01-15 ===

添加 @松鼠奧利奧 的評論:

除了運維問題之外,容器還有點像一個巨型「全靜態鏈接」,所以安全也是一個需要關注的問題…… 此前 coreos 開發了clair 檢查 quay.io 上的鏡像,一堆堆的都存在 CVE 已公布的安全問題……

安全性確實也是一個問題。


virtualenv + virtualenvwrapper + pip pipreqs

virtualenvwrapper 生成的虛擬環境都在同一個目錄下,拷貝這個目錄到其他伺服器就可以使用


……只是作一下說明,其實依賴的包除了整體複製一份virtual environment這種主流做法外,還可以選擇帶著site package一起打包部署的……


nginx+uwsgi+virtualenv

依賴寫在一個requirement.txt上,寫死版本號

pip install -r requirement.txt

不用docker


Python 應用的部署是一個很大的話題,至少是比較複雜的事情,現行的方案大多只是解決了某一方面的問題,或者把某個複雜的問題變成了另一個複雜的問題(或另一種複雜)罷了。

拋磚引玉,為什麼Python 應用的部署會成為一個問題?這裡暫時只談服務端部署,畢竟Py目前在服務端的應用還是居多,PyQt之流暫不討論。討論時主要與PHP與Java做比較,Ruby高度類似Py不參與,GoLang等則會編譯至二進位可執行文件,可比較性不大。同時的同時,這裡。。。只挖坑不管埋,下面這些問題,我也沒想明白,尚未找到一個萬全之策。

那麼,為什麼Python 應用的部署會成為一個問題呢?首先的首先,Python服務端應用的部署處於一個兩難的境地,既不像PHP那樣丟文件到伺服器就行,也不像Java那樣有個標準的規範可以直接打包到war。造成了部署複雜這一固有印象,同時另一些問題下,導致這個問題更加複雜。

1,操作系統問題,PHP可以非常容易的與IIS共處,但Python的IIS庫(雖然貌似只支持django)似乎已經爛尾了,幾乎已經沒有人在windows下做生產部署了,同時去看看各雲伺服器廠商,觀察他們的windows server的銷量就知道這個問題有多嚴重了。但同時J2EE在windows下依然可以很歡快,很多人認為PHP比Py更流行的原因在於windows下的執行環境。

2,需求的多樣化加劇了這個問題,py生態中對於性能的追求很過分,有幾多Py web框架數得過來嗎,每個web框架的運行環境甚至原理完全不一樣,舉栗子,wsgi、uwsgi、fastcgi都是可以的,django、flask、web.py、bottle這些鼎鼎大名的web框架還只能簡單歸於一類,tornado、twisted web等再歸於一類,部署他們與部署wsgi app完全不同的,好複雜。

甚至的甚至,一個Web開發我們將之拆分成framework、template engine,ORM等等好些部分,談到這個問題我只想說,我想靜靜。

上面兩點應該是python app獨有的問題了,下面一些嘈點,對比其他服務端編程語言來說一般都是半斤八兩。

1,版本差異,語言迭代時新特性太多導致語言層面的不兼容。2與3兩線開戰,2.6與2.7就有太多不一樣的地方,3.3與3.4,3.5都不同,操作系統內置的版本與應用自己的版本不一致(CentOS 6使用 py2.6),是否使用VirtualENV等問題。


比J2EE或者PHP,Python起點上似乎就輸了一籌,但實際上其他生態在這個問題上也是八斤八兩,Java有1.6,1.7,1.8,有
Oracle
JDK與OpenJDK,你要用了lambda那1.6上依然死翹翹,但似乎開發者使用這些新特性時節制些;PHP有HHVM,有5.x,7.0,有
5.1,5.2,5.5,5.6等。而且此二者還沒有類似VirtualENV這種東東。

2,庫,多數庫需要從pypi下載,受限的網路環境未必允許這一點,與國外伺服器連接也受限於國情。Java的Maven更難用,同時Maven center也慢到爆,PHP還沒有pypi這種東東。

3,依賴及編譯問題,與JVM生態不同,Python很多庫仍然傾向於使用C/C++實現性能密集部分,而Java則傾向於純Java實現。既然使用了C/C++,則會有編譯問題,開發機器若使用windows就必須安裝VS(或VC express)了,且X86與X64也將存在二進位不兼容的情況。但同時我們也需要認識到,Java有部分庫也分為x86與x64的區別,連JDK自身也有X86與x64的區別,更何況Java在其他平台上(如ARM等)幾無作為;PHP中使用C開發的庫比較少,多限於Web,需要編譯的仍然要手動編譯,但其生態中,Windows上多提供預編譯版。

4,多數python服務端應用有非同步進程的概念,pyer都無法忍受阻塞,發個郵件都是非同步的吧。部分技術點使用傳統的請求響應模型不再好使,如websocket的支持,幸好tornado、twisted等同時能hold住這些。非同步進程、工作進程該如何部署與運行,這方面其他兩種編程語言也沒有處理,單純採取不作為態度。

那怎麼搞?

docker的確不是銀彈,個人嘗試了三四次終放棄。我轉一下我之前提到的docker學習、使用中遇到的一些問題,又過去了半年左右了,中間簡單嘗試了一次,仍然沒成功。。。至於Python程序的部署問題,已經說了挖坑不管埋,靜候大牛的出現。

========docker粉請閃開========

半年前噴docker的幾點,輕拍。

1、都說容器可方便的解決依賴,難道docker本身就不是依賴了?滿地跑的CentOS5、以及6系列,跑Docker本身就要得折騰,都被無視了?2.6的內核,生產中應該還是主流吧。(補,現在這個也越來越少了~)

2、都說容器方便移植,可真的方便嗎,打包後的容器,少則兩三百兆,多則G級,相比傳個war包、相比easy_install,真的方便么。要是生產伺服器不在本地,還跨IDC、拷貝幾百兆的痛苦。還有大家都沒用過什麼堡壘機之類的么,要是不能訪問外網如何docker build?

3、都說虛擬化安全,可事實上大部分damon的docker進程都以root許可權跑著,相比最簡單的chroot jail機制,沒見哪裡更安全啊。的確Dockerfile能指定運行用戶,不過我要是不用docker,直接useradd、su不是更方便么?

4、都說docker簡化部署,美好的情景是只需要幾個「docker build」、「docker run」命令,一分鐘即可解決所有部署難題,可你造一個Dockerfile里的apt update要運行多久么。另外,難道大家訪問docker Repository很快么。我也覺的部署有點麻煩,但覺得docker也只是換成了另一種麻煩而已~

5、Dockerfile,怎麼看都只是一種簡單的類SQL的DSL語言,連DOS批處理都不夠,能應付「部署」會遇到的那些操蛋的問題么?隨便一個網路超時或者版本變遷都夠折騰的吧,嚴重的不放心~ (補,這的確是我不會用,構建環境時,請各種使用國內源,操作系統 pip)

6、對於Python,絕大多數人的開發,應該都會用到使用了C擴展的包吧,先給Docker裝個編譯器,整套編譯環境(gcc, g++, autoconf, make),如果這個C庫依賴其他C庫(libxml2,libpg-devel,pcre-devel)......我看還是算了吧。


pyenv + 自建pypi源,沒有sei了。


對於互聯網應用,依賴問題的最佳解決方案就是靜態聯編式的打包——我指的是思路而不是具體技術。

按照這個思路,要麼在語言層面上搞定它,比如說golang,如果是其它語言,用docker就對了


AWS Codedeploy


virtualenv加fabric,20台的伺服器 沒什麼壓力


我以前把所有物理機全部虛擬化了,使用esxi,然後桌面用vmware打包好後,做成模版,在發布,以後只需要改一些配置就可以了,環境依賴全部搞定。


Tutorial — dh-virtualenv 0.10 documentation

disclaimer: 沒用過

另外一個方案是 Docker ……


編譯機上:

  1. 檢出代碼

  2. virtualenv venv
  3. source venv/bin/activate
  4. pip install -r requirements.txt

  5. 整個目錄同步到正式環境

自己做個工具把這些個步驟自動化一下。

編譯機要能訪問pypi倉庫,編譯機處理器架構、Linux發行版和配置、項目目錄等要盡量和正式環境一致。

Python項目的部署比Java還是麻煩多了。


要看部署的環境,

如果基本是手工,物理機部署,便捷易行的方案就是使用docker,將項目依賴的各種庫build好之後,把代碼放一部分進去,build好鏡像,然後放個腳本在啟動時執行:

1. 拉取最新代碼

2. 刪除不安全文件並且更改配置

3. 啟動wsgi

在windows上跑centos都沒有問題。

要是在OpenStack裡面部署的話,需要能獲得真實IP,然後可以藉助cloud-init做初始化工作。

更為複雜的部署可以利用ansible來實現。


試試docker吧,只要依賴成功安裝一次,就可以在任意多的伺服器上快速部署,無需反覆安裝依賴。


推薦閱讀:

DevOps 的意義
在 2016 年做 DevOps 是一種什麼樣的體驗?
基於Docker持續交付平台建設的實踐
2017 Web 開發者學習路線圖

TAG:Python | 互聯網公司 | virtualenv | DevOps |