使用Docker部署Python應用的一些經驗總結
本篇文章源自作者團隊在長期開發過程中總結的寶貴經驗,其中Supervisor、Gunicorn以及Nginx更是在使用Python開發Web應用時最常用的軟體,因此對於打算使用Docker部署Python應用的讀者而言,這些最佳實踐是很有參考價值。同時希望各位在日常實踐過程中,也能將各自踩到過的“坑”以及寶貴的經驗分享出來,大家共同進步!
我們可以使用Docker簡單而高效的部署Python應用,同時,也有一些最佳實踐來幫助我們愉快的完成部署。當然,也不是說這些最佳實踐就是完成部署的唯一方式,只不過我們團隊發現它們具有高可用性,並且容易維護。注意本文中大多數內容都只是代表我的立場,基於Docker的實現方式有很多,你可以隨便選擇。本文中我不會過多的介紹Volume,因為它可能需要一個單獨的話題來解釋。我們通常會使用Volume將原始碼複製到容器中,而不是在每次執行時都重新構建。
DEBIAN_FRONTEND
Docker使用者應該都很熟悉這個環境變數,它告知作業系統應該從哪兒獲得使用者輸入。如果設定為”noninteractive”,你就可以直接執行命令,而無需向使用者請求輸入(譯者注:所有操作都是非互動式的)。這在執行apt-get命令的時候格外有用,因為它會不停的提示使用者進行到了哪步並且需要不斷確認。非互動模式會選擇預設的選項並以最快的速度完成構建。
請確保你只在Dockerfile中呼叫的RUN命令中設定了該選項,而不是使用ENV命令進行全域性的設定,因為ENV命令在整個容器執行過程中都會生效,所以當你通過BASH和容器進行互動時,如果進行了全域性設定那就會出問題。例子如下:
# 正確的做法 - 只為這個命令設定ENV變數 RUN DEBIAN_FRONTEND=noninteractive apt-get install -y python3 # 錯誤地做法 - 為接下來的任何命令都設定ENV變數,包括正在執行地容器 ENV DEBIAN_FRONTEND noninteractive RUN apt-get install -y python3
requirements.txt
相比於基本的程式碼(codebase),應用的依賴很少發生變化,因此我們可以在Dockerfile中安裝專案依賴,這也可以加快之後的構建速度(之後的構建只需要構建變更的程式碼)。Docker容器的層級構建可以快取依賴安裝的過程,所以之後的的構建速度會非常快,因為它不需要重新下載和構建依賴。
檔案順序
按照上面的思路(利用快取)來推斷,檔案新增到容器的順序至關重要。我們應該把頻繁變更的檔案放置到Dockerfile的下方,以便充分使用快取來加速Docker的構建過程。例如,應用配置、系統配置和依賴都很少改變,我們就可以把它們放到Dockerfile的頂部。而原始檔,比如路由檔案、檢視(views)和資料庫程式碼會經常發生改變,所以我們就可以把它們放在Dockerfile的下方,注意是Docker配置命令(EXPOSE、ENV等)的下方。
另外,不要考慮如何將你的檔案拷貝到Docker,它不會加快你的構建速度,因為大多數的檔案根本不會用到,比如應用原始檔。
應用金鑰
之前我們一直不知道如何把應用金鑰安全的傳遞給應用,後來我們發現可以使用docker run
命令中的env-file
引數。我們會把所有的金鑰和配置都放在app_config.list檔案中,然後通過這個檔案交付給應用。具體如下:
docker run -d -t -—env-file app_config.list <image:tag>
這個方法允許我們簡單地改變應用設定和金鑰,而無需重建一個容器。
注意:請務必確保app_config.list在.gitignore檔案的記錄中,不然它不會被檢錄到原始檔中。
Gunicorn
我們使用Gunicorn作為容器內部的應用伺服器,Gunicorn非常的穩定並且效能很好,它有非常多的配置選項,比如指定worker數量和型別(green threads、gevent等)的能力,你可以根據負載來調整應用,以獲得最佳效能。
啟動Gunicorn很簡單:
# 安裝 pip3 install gunicorn # 執行伺服器 gunicorn api:app -w 4 -b 127.0.0.1:5000
最後是在Nginx後面執行你的應用伺服器,這樣你可以進行負載均衡。
supervisord
你是不是想過在容器中執行多個程式?我想Supervisord絕對是你的最佳輔助工具。假設我們想部署這樣一個容器,它包含Nginx反向代理以及Gunicorn應用。你通過BASH指令碼可能就能實現,但是讓我們想更加簡潔一點。
Supevisor是“一個程式控制系統,它支援使用者在類UNIX作業系統上,監視並控制一些程式”。聽起來很完美!你需要先在你的Docker容器內安裝Supervisor。
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y supervisor
為了讓Supervisor知道該執行什麼以及如何管理程式,我們接下來需要為它寫一個配置檔案。
[supervisord] nodaemon = true # 這個會讓supervisord執行在前端 [program:nginx] # 你想執行的第一個程式的命名 command = /usr/sbin/nginx # nginx可執行程式的路徑 startsecs = 5 # 如果nginx保持開啟5s,我們視為啟動成功 [program:app-gunicorn] command = gunicorn api -w 4 -b 127.0.0.1:5000 startsecs = 5
這是非常基本的配置,它還有很多的配置項,比如控制日誌、stdout/stderr重定向、重啟策略等。這個工具真不錯。
一旦你完成了配置,請確保Docker將其複製到了容器中。
ADD supervisord.conf /etc/supervisord.conf
讓Supervisor作為容器的自啟動命令。
CMD supervisord -c /etc/supervisord.conf
它將會在容器啟動的時候,執行Gunicorn和Nginx。如果已經配置過了,那將會按需重啟它們。
學到的東西以及未來的目標
我們已經花了很長時間在Docker中部署程式碼,並且接下來會投入更多的時間。在使用Docker的過程中,我們學到的最重要經驗就是如何最小化思考(think minimally)。在一個容器中執行你的整個系統真的很誘人,但是在應用各自的容器中執行應用程式卻更容易維護。一般情況下,我們會在容器中執行Nignx和Web伺服器,並且在一些場景中,使用單獨的容器來執行Nginx卻沒有任何優勢,它可能只會增加複雜度。我們發現對於大多數情況,它在容器中的開銷是可接受的。
我希望這些資訊對各位有價值!當我們團隊學到更多最佳實踐時,我會更新這篇文章。
相關文章
- docker使用經驗總結(三、Docker compose基礎應用)Docker
- docker學習系列16使用過程的一些經驗總結Docker
- 4年使用經驗,總結Django一些開發經驗Django
- 後端應用分層經驗總結後端
- 使用 Docker 部署 Node 應用Docker
- 使用七牛雲端儲存的一些經驗總結
- [心得]python pip私人庫安裝部署經驗總結Python
- 分享一些我自己的docker使用經驗Docker
- 開發中的一些經驗總結
- mysql使用經驗總結MySql
- Docker容器化部署Python應用DockerPython
- 如何使用 docker 部署前端應用Docker前端
- 總結Django一些開發經驗Django
- 創業失敗的一些經驗總結創業
- mysql索引使用經驗總結MySql索引
- Git Flow 使用經驗總結Git
- Docker常用的應用部署Docker
- 內部業務系統的一些經驗總結
- 用WSL2+Docker Desktop部署InLong的坑和經驗Docker
- JavaCPP技術使用經驗總結Java
- OV7670使用經驗總結
- 使用報表工具經驗總結
- 在生產環境使用Docker部署應用Docker
- Docker_Docker應用部署4Docker
- Docker部署Angular應用DockerAngular
- Android移動應用開發中常見的經驗技巧總結Android
- 移動應用可用性測試的實踐經驗總結
- 使用 Golang 寫爬蟲經驗總結Golang爬蟲
- Windows RocketMQ使用方法經驗總結WindowsMQ
- Java應用Docker化部署GC變長的踩坑經歷JavaDockerGC
- 工作經驗總結
- vue經驗總結Vue
- mysql經驗總結MySql
- Java經驗總結Java
- Storm經驗總結ORM
- Resin 經驗總結
- 使用Docker容器化部署實踐之Django應用部署(一)DockerDjango
- 關於使用者體驗的一些總結