返回部落格

在 Ubuntu 20.04 上使用 Docker 建置與部署 Flask 應用程式

在 Ubuntu 20.04 上使用 Docker 建置與部署 Flask 應用程式

簡介

Docker 是一個開源的容器平台。它是一個輕量級、虛擬化、可移植、軟體定義的標準化環境,允許軟體與運行在實體主機上的其他軟體隔離運行。Docker 提供了一個替代虛擬機的輕量級選擇。同時,它還提供了應用程式的可移植性、效能、敏捷性和可擴展性。如需完整的 Docker 生態系統指南,請參閱我們關於使用 Docker 進行容器化的詳細概述.

Flask 是一個開源的微型網頁框架,使用 Python 構建。Flask 的一些優秀特性包括輕量、靈活且高度結構化。此外,它不需要任何特定的工具或外掛程式即可運行。

將 Flask 和 Docker 結合使用,可以為您提供一個輕量、靈活且具可擴展性的應用程式。得益於 Docker 容器的可移植性,您可以將其部署到多個伺服器和基礎設施中。本教學的重點是向您展示如何使用 Docker 部署 Flask 應用程式。我們還將演示如何確保應用程式未來的更新能夠生效。

先決條件

這是一個動手實作的教學,您應該建立一個能夠跟著操作的環境:

現在,讓我們開始吧!

步驟 1:準備 Flask 應用程式

我們將首先建立一個用於存放 Flask 應用程式的目錄。您可以自行選擇目錄名稱。不過,在本教學中,我們將其命名為 flask_demo。我們將把專案檔案儲存在 /var/www 目錄中,這通常是 Ubuntu 預設允許公共網際網路存取的目錄。首先,執行以下命令來建立該目錄並進入其中:

在我們專案的根目錄中,我們將建立 Flask 應用程式的基本資料夾結構。接下來,執行以下命令來建立基本結構,並加上 -p 參數以同時建立所有父資料夾:

app 資料夾存放與 Flask 應用程式相關的所有檔案,包括 viewsblueprints。Views 包含您編寫用於回應傳送到應用程式之請求的程式碼。Blueprints 有助於構建應用程式組件,並支援 Flask 應用程式中的常見模式。

顧名思義, static 資料夾存放靜態資產,例如圖片、CSS 和 JavaScript 檔案。 templates 目錄則存放專案的所有 HTML 範本。

現在我們可以開始編寫初始化 Flask 應用程式所需的檔案。首先在 app 目錄中建立一個名為 __init__.py 的檔案,以告知 Python 直譯器 應該將 app 目錄視為一個套件。在您的終端機上執行以下命令,以使用 nano 編輯器開啟該檔案:

我們在 Python 中使用套件將模組分組到邏輯命名空間或階層中。模組化允許將程式碼分解為執行特定功能的獨立且易於管理的區塊。

之後,在編輯器中開啟的 __init__.py 檔案中,新增以下程式碼片段以啟動 Flask 實例,並從您將在後續步驟中建立的 views.py 中匯入邏輯:

完成後,請按 Ctrl + OENTER 以儲存檔案,然後使用 Ctrl + X 關閉它。接下來,讓我們在 views.py 資料夾內建立 app 目錄。 views.py 檔案將包含大部分的應用程式邏輯:

在檔案中加入以下程式碼片段。這段程式碼將在使用者造訪您的網站時顯示一個簡單的字串,以表示您的應用程式正在執行:

在此檔案中,我們首先匯入 Flask 應用程式執行個體。然後,我們需要加入一行來定義路由: @app.route(/)@app.route(/) 行在 Flask 中被稱為 decorator。您可以使用裝飾器將額外的功能注入到一個或多個函式中。在此案例中,我們將對路由的呼叫傳遞給 / 到 home 函式。當使用者造訪此路由時,他們將會看到以下文字: "Our Flask application is running!".

接下來,您將建立 uwsgi.ini 檔案,以儲存應用程式的 uWSGI 設定。 uWSGI 是 Nginx 的一種部署選項,可用作協定和應用程式伺服器。執行以下命令,使用 nano 編輯器在專案的根目錄中建立該檔案:

在開啟的檔案中,加入以下程式碼片段:

此檔案包含一些指令。我們在下方定義它們的用途:

  • module – 定義提供 Flask 應用程式服務的模組。我們已將模組設定為 main,這會引用根目錄中的 main.py 檔案。我們將在下一步中建立此檔案。
  • callable – 指示 uWSGI 使用從應用程式匯出的 app 執行個體。
  • master – 確保應用程式持續執行,以在重新載入整個應用程式時將停機時間降至最低。

完成後,儲存並關閉檔案。

現在您可以建立 main.py 檔案,以確定應用程式的進入點。 uWSGI 將讀取此檔案以了解如何與應用程式互動。執行以下命令,以建立 main.py  檔案,使用 nano 於專案的 root directory 中:

在檔案中加入以下行,這將匯入在應用程式套件中建立的 Flask 執行個體:

在此步驟中,您要做的最後一件事是定義應用程式執行所需的相依性。我們將在名為 dependencies.txt 的檔案中定義這些相依性。當 Docker 建置您的應用程式映像檔時,它將執行 pip (package manager) 命令來安裝相依性。使用以下命令在根目錄中開啟該檔案:

到目前為止,在我們的專案中,我們只需要一個相依性: Flask。因此,我們可以加入以下行來引用我們專案所需的正確 Flask 版本:

我們決定使用 Flask version 2.0.1 作為相依性。這是撰寫本教學時的最新版本。您可以從 Flask Changes 頁面中了解更多關於各個版本的資訊。這樣就完成了 Flask 應用程式的設定。現在讓我們準備用於部署的 Docker 設定。

Step 2: Configure Docker

要設定 Docker 部署,我們將建立兩個檔案: Dockerfile 以及 start.shDockerfile 包含構成 Docker 映像檔的宣告行。而 start.sh 是一個基本的 Shell 指令碼,用於建置映像檔並從 Dockerfile 啟動容器。在專案的根目錄中,執行以下命令以建立 Dockerfile:

此檔案包含 Docker 映像檔所需的設定。接下來,加入以下程式碼片段以指定相依性以及如何建置映像檔:

中的第一行Dockerfile 定義了我們用來構建映像檔的基礎映像檔。在這種情況下,我們將基於 tiangolo/uwsgi-nginx-flask,可從 DockerHub 取得。我們選擇這個特定的映像檔是因為它支援許多 Python 版本。

我們還指定了要更新映像檔。然後,我們需要添加 bash 指令 processonano 文字 編輯器,以及 git 用戶端,用於從版本控制存放庫(例如 )拉取和推送原始碼GitHub, Bitbucket, Gitlab。帶有 ENV 指定要在容器中使用的環境變數。

The COPY 指令將依賴項複製到容器中。 RUN 指令會調用 pip 套件 管理員 來解析 dependencies.txt 檔案並 安裝 這些依賴項。編輯完成後,儲存並關閉檔案。

接下來,您將建立 start.sh 腳本。此腳本將包含 Docker 指令來 構建運行 該映像檔。雖然您可以在終端機上逐步執行這些指令,但我們認為將它們添加到 Shell 腳本中,並只需在終端機中用一個指令調用它會更乾淨。

在定義此檔案的內容之前,我們必須先確定一個其他服務未使用的空閒連接埠。我們將使用連接埠 45644。不過,您可以選擇不同的連接埠。執行以下行以檢查該連接埠是否空閒:

根據您選擇的連接埠,如果上述指令的輸出為 1,那麼它就是空閒的。否則,您可能必須選擇另一個連接埠並再次嘗試該指令:

Flask application Port Check

既然我們已經確定了一個空閒連接埠,我們現在可以透過運行以下指令,在專案的根目錄中使用 nano 建立該檔案:

在此檔案中,添加以下程式碼片段:

第一行,被稱為 shebang,指定這是一個 bash 檔案,應作為指令執行。第二行宣告了一個名為 app_name 的變數。我們使用此變數來設定映像檔和容器名稱。第三行指示 Docker 構建 基於當前目錄中 Dockerfile 定義的映像檔。該映像檔將根據變數命名為 docker-flask-demo

最後一行建立了一個名為 docker-flask-demo,如我們定義的變數所示。 -d 旗標使容器在指令執行完畢後,以分離狀態在背景繼續運行。 -p 旗標將伺服器上的連接埠綁定到容器上的特定連接埠。在這種情況下,我們將主機上的連接埠 45644 掛載到 Docker 將在容器中公開的連接埠 80

我們使用 -v 旗標來指定要掛載到容器上的 Docker 磁碟區$PWD 變數是一個預設的 Linux 變數,保存您在特定時間所在的 目前目錄 的路徑:

Flask application pwd

在我們的案例中,我們將整個專案目錄掛載到容器的 /var/www 目錄。Docker 設定現在已準備就緒。您可以透過執行以下指令,基於構建的映像檔來構建映像檔並啟動容器:

等待腳本運行完畢,然後執行以下 Docker 命令以列出所有運行中的容器:

輸出將顯示運行中的容器:

Demo Docker

您應該會在運行中的容器列表中看到名稱為 docker-flask-demo 的容器。找到您伺服器的公用 IP 並在瀏覽器中透過指定的連接埠存取它: http://your-server-public-ip:45644.

您應該會看到類似的輸出:

Flask App Running

如果您在瀏覽器中看到上述內容,則表示您已成功部署 Flask 應用程式。接下來,我們將修改檔案並透過範本向使用者提供內容。

步驟 3:透過範本檔案提供內容

在 Flask 中,範本 用於向網站訪客顯示靜態和動態內容。我們將向您展示如何建立一個 HTML 範本,並在使用者造訪特定路由時將其提供給他們。例如,這可以是首頁或「關於」頁面。

在您的終端機上執行以下命令,以在 index.html 檔案建立於 app/templates 目錄中:

然後,將以下程式碼片段新增至該檔案:

完成後儲存並關閉檔案。此外,使用以下命令建立另一個頁面,我們稱之為「關於」頁面:

將以下程式碼片段新增至該檔案:

完成後儲存並關閉檔案。接下來,修改 app/views.py 檔案以引用範本以及實際頁面的路由:

修改檔案,使其看起來像這樣:

完成後儲存並關閉檔案。您所做的變更在停止並重新啟動容器之前不會生效。執行以下 Docker 指令來停止和啟動容器。請注意我們之前定義的容器名稱:

容器啟動並運行後,造訪首頁和關於頁面以查看一些新內容:

Flask application Index

 Flask application 1

到目前為止,您已經建立了一個可以向網站訪客提供內容的 Flask 應用程式。以下是該專案的檔案結構:

File Structure

您可能已經注意到,我們必須重新啟動 Docker 容器才能套用新的變更。在下一步中,我們將使其自動化,以確保減少停機時間。

步驟 4:設定應用程式檔案更新以自動重新載入

我們經常會對應用程式進行變更,以改進邏輯、使用者介面或新增一些依賴項。為了使這些變更生效,可能需要您重新啟動 Docker 容器。幸運的是, uWSGI 具有一個名為 touch-reload 的功能,用於在不重新啟動容器的情況下重新載入 Python 指令碼。

開箱即用,Python 具有一個 auto-reloading 功能,它會監視整個檔案系統的變更,並在發生變更時重新整理應用程式。雖然自動重新載入有利於減少停機時間,但它可能會消耗大量資源。因此,不建議在生產環境中使用。

讓我們看看如何使用 touch-reload 來監視特定檔案的變更,並在發生變更時重新載入應用程式。使用 nano 編輯器修改 uwsgi.ini 檔案:

新增醒目提示的行,使其看起來像這樣:

完成後儲存並關閉檔案。新增的行指定了一個檔案,修改該檔案將觸發應用程式的重新載入。但是,為了使此條件在未來的修改中生效,您必須先重新啟動容器:

您現在可以修改 app/views.py 檔案以示範自動重新載入的工作原理:

將 home 函數傳回的字串變更為醒目提示的內容:

完成後儲存並關閉檔案。

在瀏覽器中開啟應用程式的首頁: http://your-server-public-ip:45644.

您還不會看到任何變更。這是因為 touch-reload 條件偵測的是對 uwsgi.ini 檔案的變更。您可以使用 touch 來啟用該條件,從而使用以下指令重新載入整個應用程式:

現在,如果您重新載入首頁,您將會看到顯示的新變更:

Touch Reload

未來,如果您進行任何變更,只需執行以下指令 sudo touch uwsgi.ini ,整個應用程式將以更短的停機時間重新載入。本教學到此結束。

結論

在本教學中,您使用 Docker 映像檔和容器實作並部署了一個 Flask 應用程式。為了透過避免重新啟動容器來減少停機時間,您設定了 touch-reload 來監聽特定檔案的變更,並自動重新載入整個應用程式。最後,您在瀏覽器中測試了所有這些功能,以確保其正常運作。

Docker 可確保更快的部署,並允許輕鬆擴充應用程式。如果您想了解更多關於各種 Docker 指令的資訊,請參閱這篇關於 如何在 Ubuntu 上安裝和使用 Docker.

如需更多關於 Docker 的資源,請造訪 我們的部落格,您可以參考以下內容:

祝您運算愉快!

author

Pranay Kapgate

作者 · CloudSigma

Preslav Dobrev 是 CloudSigma 的創意設計師,專注於透過傳統與創新行銷渠道建立一致的企業形象。他擅長將藝術願景與策略行銷相融合,創造具有影響力的品牌敘事。

留言

目前尚無留言。成為第一個留言的人吧。