使用Docker開(kāi)發(fā)python Web 應(yīng)用
本文中,我將嘗試展示用Docker開(kāi)發(fā)python應(yīng)用(主要是Web應(yīng)用)的可行方法。雖然我本人專注于Python的Flask微框架,但本文目的是演示如何通過(guò)Docker更好地開(kāi)發(fā)和共享應(yīng)用程序,(由任何語(yǔ)言和框架開(kāi)發(fā)的應(yīng)用程序)。Docker通過(guò)封裝依賴項(xiàng),大大減少了開(kāi)發(fā)環(huán)境和正式產(chǎn)品的差距。
大多數(shù)Python開(kāi)發(fā)人員在開(kāi)發(fā)中使用virtualenv。它提供了一種易用的機(jī)制讓?xiě)?yīng)用程序使用自己專用的依賴項(xiàng),這些依賴項(xiàng)可能與在其它應(yīng)用程序或操作系統(tǒng)存在沖突(尤其是不同的Pyhton版本,還有不同的庫(kù)版本等等)。個(gè)人而言,我對(duì)virtualenv一直沒(méi)有太大興趣,原因如下:
我經(jīng)常忘記啟用它,或者在切換工程時(shí)忘記切換它,這會(huì)遇到含糊的出錯(cuò)信息,另人倍感困惑。
它無(wú)法提供“純粹的”隔離,只能是Python級(jí)別的隔離(系統(tǒng)庫(kù)和非python的依賴項(xiàng)仍然會(huì)出問(wèn)題)。
我通常不想在正式產(chǎn)品中運(yùn)行它,這就意味著在開(kāi)發(fā)環(huán)境和正式產(chǎn)品的不一致。
它讓人感覺(jué)有點(diǎn)“黑客”作法:它是依靠修改腳本和設(shè)置新路徑實(shí)現(xiàn)的。
( 查看 pythonrants的這篇文章 了解更多為什么你可能不想用virtualenv )
那么,怎么做Docker才能變得更好呢?Docker本質(zhì)上提供了非常輕量化的VMs(在說(shuō)法上可以稱為“容器”),我們可以使用其創(chuàng)建一個(gè)高標(biāo)準(zhǔn)隔離并能大大減少失配的開(kāi)發(fā)和產(chǎn)品環(huán)境。(如果你不熟悉Docker,卻還想學(xué)習(xí)更多,你可以查看我在愛(ài)丁堡技術(shù)座談會(huì)上介紹Docker的談話)。
當(dāng)我們建立一個(gè)小型的可視化Web APP,我自己和Mark Coleman使用這種方法(文檔在這)。這(里面)劃出了一個(gè)基本鏡像安裝Python 2.7,還有一些Flask管理以及PostgreSQL的內(nèi)容。我會(huì)依據(jù)這個(gè)鏡像去開(kāi)發(fā)一個(gè)hello world的Web應(yīng)用。我假設(shè)你是在Linux上開(kāi)發(fā),并且你已經(jīng)有g(shù)it,還安裝了Docker,MacOS的指令應(yīng)該非常類似。通過(guò)克隆和建立基本鏡像開(kāi)始:
$ git clone https : //github.com/mrmrcoleman/python_webapp $ docker build – t python _ webapp .
現(xiàn)在,我們需要為容器中添加一些代碼并詳細(xì)寫(xiě)明。我們打算新建一個(gè)僅僅指向Docker鏡像的項(xiàng)目來(lái)完成這項(xiàng)工作,而不是直接修改之前的項(xiàng)目。
創(chuàng)建一個(gè)具有下列結(jié)構(gòu)的新項(xiàng)目:
├── Dockerfile ├── example _ app │ ├── app │ │ ├── __init__ . py │ │ └── views . py │ └── __init__ . py ├── example_app . wsgi
或者克隆該地址的示例項(xiàng)目: https://github.com/amouat/example_app.git
在example_app/app/_init_.py中寫(xiě)入:
from flask import Flask app = Flask ( __name__ ) from app import views
使另一個(gè)_init_.py為空。在views.py中寫(xiě)入:
from app import app @ app . route ( ‘/' ) @ app . route ( ‘/index' ) def index () : return “Hello, World!”
以上就是我們的一個(gè)hello world應(yīng)用的最小flask版本。我在 這個(gè)教程中也使用過(guò)類似的代碼,所以如果你剛剛接觸Flask或者Python,你可以根據(jù)上述提到的教程,使用Docker而不是virtualenv繼續(xù)學(xué)習(xí)。
為了使之運(yùn)行在Docker容器內(nèi)部,我們還需要做一些操作。在我們的實(shí)例Apache服務(wù)器中,example_app.wsgi文件包含了連接Python代碼和web服務(wù)器的指令。該文件應(yīng)當(dāng)包含下列內(nèi)容:
import site site . addsitedir ( ‘/opt/example_app/' ) from app import app as application
最終,我們需要一個(gè)Dockerfile來(lái)構(gòu)建容器并運(yùn)行容器。在我們的實(shí)例中,它看起來(lái)是這樣的:
FROM python_webapp MAINTAINER amouat ADD example_app . wsgi / var / www / flaskapp / flaskapp . wsgi CMD service apache2 start && tail – F / var / log / apache2 / error . log
ADD那行為啟動(dòng)WSGI注入了一些代碼。CMD那行在啟動(dòng)容器,啟動(dòng)apache web服務(wù)器時(shí)獲取任何可能的錯(cuò)誤信息,并將其發(fā)送至stdout。
如果你下列操作:
$ docker run – p 5000 : 5000 – v $( pwd ) / example_app :/ opt / example_app / – i – t example_app
你應(yīng)當(dāng)會(huì)得到這樣的回饋:通過(guò)瀏覽器打開(kāi)地址localhost:5000,你會(huì)看到你的網(wǎng)站正在運(yùn)行。如果你實(shí)在VM或者vagrant中運(yùn)行,記得打開(kāi)5000端口。
現(xiàn)在我們運(yùn)行了web服務(wù)器,已經(jīng)非常接近我們?cè)诋a(chǎn)品中使用的東西了(我有意的使用Apache來(lái)做這點(diǎn)而不是Python默認(rèn)的web服務(wù)器)。我們通過(guò)從主機(jī)向容器映射的方式向容器中注入代碼;也可以在Dockerfile命令行中是用ADD來(lái)添加代碼,但那樣的話當(dāng)我們隊(duì)代碼進(jìn)行改動(dòng)時(shí),每次都需要重新構(gòu)建容器。
然而,這仍然不是很好 ;開(kāi)發(fā)中我們真的希望使用很大程度上幫助我們調(diào)試的Python web服務(wù)器。該高興的是我們不用對(duì)Dockerfile進(jìn)行任何修改。在example_app文件從創(chuàng)建一個(gè)run.py文件開(kāi)始,按照一下內(nèi)容:
! flask / bin / python from app import app app . run ( debug = True , host = ‘0.0.0.0' )
這將啟動(dòng)Python的帶調(diào)試的web服務(wù)器并監(jiān)聽(tīng)所有連接,我們也能從容器外訪問(wèn)?,F(xiàn)在用下列命令重啟容器:
$ docker run -p 5000:5000 -v $(pwd)/example_app:/opt/example_app/ -i -t example_app python /opt/example_app/run.py
你能看到網(wǎng)頁(yè)又運(yùn)行了。這次我們顯式地提供運(yùn)行的命令(”python /opt/example_app/ryn.py”),它覆蓋了Dockerfile中的CMD行的設(shè)置。現(xiàn)在如果編輯在主機(jī)上的源程序,就能馬上看到網(wǎng)頁(yè)上的改變。
讓我們花點(diǎn)時(shí)間看看我們的收獲:
一個(gè)運(yùn)行在隔離容器中的web應(yīng)用,容器完全封裝了應(yīng)用的Python依賴項(xiàng)和系統(tǒng)依賴項(xiàng)。
能夠使用現(xiàn)有編輯器或IDE開(kāi)發(fā)代碼并直接查看變化,就像在本地編輯一樣。
比以前更接近正式產(chǎn)品的運(yùn)行環(huán)境。
沒(méi)有使用virtualenv。
如果你想知道如何以這種方式建立程序發(fā)布的途徑,可以看看Mark Coleman寫(xiě)的關(guān)于前面提到的可視化Web應(yīng)用的文章。
不幸的是,這一切還不完美。還有下列幾個(gè)問(wèn)題:
你可能仍會(huì)遇到需要使用virtualenv或其等價(jià)解決方案的情況,例如庫(kù)的操作系統(tǒng)版本與你的程序所需版本間的沖突。
我們還沒(méi)完全解決數(shù)據(jù)托管的問(wèn)題,仍需做某些測(cè)試。
我假設(shè)的“產(chǎn)品”是一個(gè)Docker容器,但實(shí)際情況常常并非如此而且Docker托管本身也剛剛起步。
盡管如此,我仍然認(rèn)為這向軟件開(kāi)發(fā)的更好未來(lái)邁了一大步,大大減輕了部署軟件和管理依賴項(xiàng)的痛苦。
相關(guān)文章
關(guān)于docker?cgroups資源限制的問(wèn)題
cgroups是一個(gè)非常強(qiáng)大的linux內(nèi)核工具,他不僅可以限制被namespace隔離起來(lái)的資源,還可以為資源設(shè)置權(quán)重、計(jì)算使用量,這篇文章主要介紹了docker?cgroups資源限制,需要的朋友可以參考下2022-09-09docker打包node項(xiàng)目的過(guò)程講解
今天小編就為大家分享一篇關(guān)于docker打包node項(xiàng)目的過(guò)程講解,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2019-03-03Docker+K8S 集群環(huán)境搭建及分布式應(yīng)用部署
這篇文章主要介紹了Docker+K8S 集群環(huán)境搭建及分布式應(yīng)用部署,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07Docker安裝php及yaf擴(kuò)展文件內(nèi)容
這篇文章主要為大家介紹了Docker安裝php及yaf擴(kuò)展文件內(nèi)容,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-11-11使用docker搭建go環(huán)境的簡(jiǎn)單步驟
最近公司里面的項(xiàng)目用到了Docker,正好準(zhǔn)備學(xué)習(xí)下Golang,所以就學(xué)習(xí)Golang順便也學(xué)習(xí)下Docker怎么用的,剛好從頭開(kāi)始配置下環(huán)境,這篇文章主要給大家介紹了關(guān)于使用docker搭建go環(huán)境的簡(jiǎn)單步驟,需要的朋友可以參考下2023-10-10Harbor搭建Docker私有倉(cāng)庫(kù)的實(shí)現(xiàn)方法
Harbor是一個(gè)由CNCF托管的開(kāi)源的Docker鏡像倉(cāng)庫(kù)管理工具,我們可以通過(guò)它快速的建立起自己的私有倉(cāng)庫(kù),本文就詳細(xì)的介紹了Harbor搭建Docker私有倉(cāng)庫(kù)的實(shí)現(xiàn)方法,感興趣的可以了解一下2021-06-06docker中mysql初始化及啟動(dòng)失敗問(wèn)題解決方案
這篇文章主要介紹了docker中mysql初始化及啟動(dòng)失敗問(wèn)題解決方案的相關(guān)資料,需要的朋友可以參考下2016-10-10一文教會(huì)你如何高效地搭建Docker私有倉(cāng)庫(kù)
Docker容器應(yīng)用的開(kāi)發(fā)和運(yùn)行離不開(kāi)可靠的鏡像管理,雖然Docker官方也提供了公共的鏡像倉(cāng)庫(kù),但是從安全和效率等方面考慮,部署我們私有環(huán)境內(nèi)的Registry也是非常必要的,這篇文章主要介紹了如何高效地搭建Docker私有倉(cāng)庫(kù)的相關(guān)資料,需要的朋友可以參考下2022-08-08