使用 Docker 作為 Python 開發環境

jopen 10年前發布 | 20K 次閱讀 Python Docker Python開發

(或者讓我們繞過virtualenv)

本文中,我將嘗試展示用Docker開發python應用(主要是Web應用)的可行方法。雖然我本人專注于Python的Flask微框架,但本文目的是演示如何通過Docker更好地開發和共享應用程序,(由任何語言和框架開發的應用程序)。Docker通過封裝依賴項,大大減少了開發環境和正式產品的差距。

大多數Python開發人員在開發中使用virtualenv。它提供了一種易用的機制讓應用程序使用自己專用的依賴項,這些依賴項可能與在其它應用程序或操作系統存在沖突(尤其是不同的Pyhton版本,還有不同的庫版本等等)。個人而言,我對virtualenv一直沒有太大興趣,原因如下:

  • 我經常忘記啟用它,或者在切換工程時忘記切換它,這會遇到含糊的出錯信息,另人倍感困惑。

    </li>

  • 它無法提供“純粹的”隔離,只能是Python級別的隔離(系統庫和非python的依賴項仍然會出問題)。

    </li>

  • 我通常不想在正式產品中運行它,這就意味著在開發環境和正式產品的不一致。

    </li>

  • 它讓人感覺有點“黑客”作法:它是依靠修改腳本和設置新路徑實現的。

    </li> </ul>

    查看 pythonrants的這篇文章 了解更多為什么你可能不想用virtualenv

    那么,怎么做Docker才能變得更好呢?Docker本質上提供了非常輕量化的VMs(在說法上可以稱為“容器”),我們可以使用其創建一個高標準隔離并能大大減少失配的開發和產品環境。(如果你不熟悉Docker,卻還想學習更多,你可以查看我在愛丁堡技術座談會上介紹Docker的談話)。

    當我們建立一個小型的可視化Web APP,我自己和Mark Coleman使用這種方法(文檔在這)。這(里面)劃出了一個基本鏡像安裝Python 2.7,還有一些Flask管理以及PostgreSQL的內容。我會依據這個鏡像去開發一個hello world的Web應用。我假設你是在Linux上開發,并且你已經有git,還安裝了Docker,MacOS的指令應該非常類似。通過克隆和建立基本鏡像開始:

    $ git clone https://github.com/mrmrcoleman/python_webapp
    $ docker build -t python_webapp .

    現在,我們需要為容器中添加一些代碼并詳細寫明。我們打算新建一個僅僅指向Docker鏡像的項目來完成這項工作,而不是直接修改之前的項目。

    創建一個具有下列結構的新項目:

    ├── Dockerfile
     ├── example_app
     │   ├── app
     │   │   ├── __init__.py
     │   │   └── views.py
     │   └── __init__.py
     ├── example_app.wsgi

    或者克隆該地址的示例項目: https://github.com/amouat/example_app.git

    在example_app/app/_init_.py中寫入:

    from flask import Flask

    app = Flask(name) from app import views</pre>

    使另一個_init_.py為空。在views.py中寫入:

    from app import app

    @app.route('/') @app.route('/index') def index():     return "Hello, World!"</pre>

    以上就是我們的一個hello world應用的最小flask版本。我在 這個教程中也使用過類似的代碼,所以如果你剛剛接觸Flask或者Python,你可以根據上述提到的教程,使用Docker而不是virtualenv繼續學習。

    為了使之運行在Docker容器內部,我們還需要做一些操作。在我們的實例Apache服務器中,example_app.wsgi文件包含了連接Python代碼和web服務器的指令。該文件應當包含下列內容:

    import site
    site.addsitedir('/opt/example_app/')
    from app import app as application

    最終,我們需要一個Dockerfile來構建容器并運行容器。在我們的實例中,它看起來是這樣的:

    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</pre>

    ADD那行為啟動WSGI注入了一些代碼。CMD那行在啟動容器,啟動apache web服務器時獲取任何可能的錯誤信息,并將其發送至stdout。

    如果你下列操作:

    $ docker build -t example_app .
    $ docker run -p 5000:5000 -v $(pwd)/example_app:/opt/example_app/ -i -t example_app

    你應當會得到這樣的回饋:通過瀏覽器打開地址localhost:5000,你會看到你的網站正在運行。如果你實在VM或者vagrant中運行,記得打開5000端口。

    現在我們運行了web服務器,已經非常接近我們在產品中使用的東西了(我有意的使用Apache來做這點而不是Python默認的web服務器)。我們通過從主機向容器映射的方式向容器中注入代碼;也可以在Dockerfile命令行中是用ADD來添加代碼,但那樣的話當我們隊代碼進行改動時,每次都需要重新構建容器。

    然而,這仍然不是很好 ;開發中我們真的希望使用很大程度上幫助我們調試的Python web服務器。該高興的是我們不用對Dockerfile進行任何修改。在example_app文件從創建一個run.py文件開始,按照一下內容:

    !flask/bin/python
    from app import app
    app.run(debug = True, host='0.0.0.0')

    這將啟動Python的帶調試的web服務器并監聽所有連接,我們也能從容器外訪問。現在用下列命令重啟容器:

    $ docker run -p 5000:5000 -v $(pwd)/example_app:/opt/example_app/ -i -t example_app python /opt/example_app/run.py

    你能看到網頁又運行了。這次我們顯式地提供運行的命令("python /opt/example_app/ryn.py"),它覆蓋了Dockerfile中的CMD行的設置。現在如果編輯在主機上的源程序,就能馬上看到網頁上的改變。

    讓我們花點時間看看我們的收獲:

    • 一個運行在隔離容器中的web應用,容器完全封裝了應用的Python依賴項和系統依賴項。

      </li>

    • 能夠使用現有編輯器或IDE開發代碼并直接查看變化,就像在本地編輯一樣。

      </li>

    • 比以前更接近正式產品的運行環境。

      </li>

    • 沒有使用virtualenv。

      </li> </ul>

      如果你想知道如何以這種方式建立程序發布的途徑,可以看看Mark Coleman寫的關于前面提到的可視化Web應用的文章

      不幸的是,這一切還不完美。還有下列幾個問題:

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!