簡介
Docker 是一個開源的容器平台。它是一個輕量級、虛擬化、可移植、軟體定義的標準化環境,允許軟體與運行在實體主機上的其他軟體隔離運行。Docker 提供了一個替代虛擬機的輕量級選擇。同時,它還提供了應用程式的可移植性、效能、敏捷性和可擴展性。如需完整的 Docker 生態系統指南,請參閱我們關於使用 Docker 進行容器化的詳細概述.
Flask 是一個開源的微型網頁框架,使用 Python 構建。Flask 的一些優秀特性包括輕量、靈活且高度結構化。此外,它不需要任何特定的工具或外掛程式即可運行。
將 Flask 和 Docker 結合使用,可以為您提供一個輕量、靈活且具可擴展性的應用程式。得益於 Docker 容器的可移植性,您可以將其部署到多個伺服器和基礎設施中。本教學的重點是向您展示如何使用 Docker 部署 Flask 應用程式。我們還將演示如何確保應用程式未來的更新能夠生效。
先決條件
這是一個動手實作的教學,您應該建立一個能夠跟著操作的環境:
- 您應該擁有一個 已安裝的 Ubuntu 20.04 作為您的初始作業環境。您還需要建立一個 具有 sudo 權限的非 root 使用者.
- 此外,您需要安裝 Docker。我們有一篇關於 如何在 Ubuntu 上安裝和操作 Docker 的教學。請按照步驟 1、2、3 和 4 進行操作。這適用於任何 Ubuntu 發行版。
- 最後,您需要安裝 Nginx。請按照我們關於 在 Ubuntu 上安裝 Nginx.
現在,讓我們開始吧!
步驟 1:準備 Flask 應用程式
我們將首先建立一個用於存放 Flask 應用程式的目錄。您可以自行選擇目錄名稱。不過,在本教學中,我們將其命名為 flask_demo。我們將把專案檔案儲存在 /var/www 目錄中,這通常是 Ubuntu 預設允許公共網際網路存取的目錄。首先,執行以下命令來建立該目錄並進入其中:
|
1 2 3 |
sudo mkdir /var/www/flask_demo cd /var/www/flask_demo |
在我們專案的根目錄中,我們將建立 Flask 應用程式的基本資料夾結構。接下來,執行以下命令來建立基本結構,並加上 -p 參數以同時建立所有父資料夾:
|
1 |
sudo mkdir -p app/static app/templates |
app 資料夾存放與 Flask 應用程式相關的所有檔案,包括 views 和 blueprints。Views 包含您編寫用於回應傳送到應用程式之請求的程式碼。Blueprints 有助於構建應用程式組件,並支援 Flask 應用程式中的常見模式。
顧名思義, static 資料夾存放靜態資產,例如圖片、CSS 和 JavaScript 檔案。 templates 目錄則存放專案的所有 HTML 範本。
現在我們可以開始編寫初始化 Flask 應用程式所需的檔案。首先在 app 目錄中建立一個名為 __init__.py 的檔案,以告知 Python 直譯器 應該將 app 目錄視為一個套件。在您的終端機上執行以下命令,以使用 nano 編輯器開啟該檔案:
|
1 |
sudo nano app/__init__.py |
我們在 Python 中使用套件將模組分組到邏輯命名空間或階層中。模組化允許將程式碼分解為執行特定功能的獨立且易於管理的區塊。
之後,在編輯器中開啟的 __init__.py 檔案中,新增以下程式碼片段以啟動 Flask 實例,並從您將在後續步驟中建立的 views.py 中匯入邏輯:
|
1 2 3 4 5 |
from flask import Flask app = Flask(__name__) from app import views |
完成後,請按 Ctrl + O 和 ENTER 以儲存檔案,然後使用 Ctrl + X 關閉它。接下來,讓我們在 views.py 資料夾內建立 app 目錄。 views.py 檔案將包含大部分的應用程式邏輯:
|
1 |
sudo nano app/views.py |
在檔案中加入以下程式碼片段。這段程式碼將在使用者造訪您的網站時顯示一個簡單的字串,以表示您的應用程式正在執行:
|
1 2 3 4 5 |
from app import app @app.route('/') def home(): return "Our Flask application is running!" |
在此檔案中,我們首先匯入 Flask 應用程式執行個體。然後,我們需要加入一行來定義路由: @app.route(/)。 @app.route(/) 行在 Flask 中被稱為 decorator。您可以使用裝飾器將額外的功能注入到一個或多個函式中。在此案例中,我們將對路由的呼叫傳遞給 / 到 home 函式。當使用者造訪此路由時,他們將會看到以下文字: "Our Flask application is running!".
接下來,您將建立 uwsgi.ini 檔案,以儲存應用程式的 uWSGI 設定。 uWSGI 是 Nginx 的一種部署選項,可用作協定和應用程式伺服器。執行以下命令,使用 nano 編輯器在專案的根目錄中建立該檔案:
|
1 |
sudo nano uwsgi.ini |
在開啟的檔案中,加入以下程式碼片段:
|
1 2 3 4 |
[uwsgi] module = main callable = app master = true |
此檔案包含一些指令。我們在下方定義它們的用途:
- module – 定義提供 Flask 應用程式服務的模組。我們已將模組設定為 main,這會引用根目錄中的 main.py 檔案。我們將在下一步中建立此檔案。
- callable – 指示 uWSGI 使用從應用程式匯出的 app 執行個體。
- master – 確保應用程式持續執行,以在重新載入整個應用程式時將停機時間降至最低。
完成後,儲存並關閉檔案。
現在您可以建立 main.py 檔案,以確定應用程式的進入點。 uWSGI 將讀取此檔案以了解如何與應用程式互動。執行以下命令,以建立 main.py 檔案,使用 nano 於專案的 root directory 中:
|
1 |
sudo nano main.py |
在檔案中加入以下行,這將匯入在應用程式套件中建立的 Flask 執行個體:
|
1 |
from app import app |
在此步驟中,您要做的最後一件事是定義應用程式執行所需的相依性。我們將在名為 dependencies.txt 的檔案中定義這些相依性。當 Docker 建置您的應用程式映像檔時,它將執行 pip (package manager) 命令來安裝相依性。使用以下命令在根目錄中開啟該檔案:
|
1 |
sudo nano dependencies.txt |
到目前為止,在我們的專案中,我們只需要一個相依性: Flask。因此,我們可以加入以下行來引用我們專案所需的正確 Flask 版本:
|
1 |
Flask==2.0.1 |
我們決定使用 Flask version 2.0.1 作為相依性。這是撰寫本教學時的最新版本。您可以從 Flask Changes 頁面中了解更多關於各個版本的資訊。這樣就完成了 Flask 應用程式的設定。現在讓我們準備用於部署的 Docker 設定。
Step 2: Configure Docker
要設定 Docker 部署,我們將建立兩個檔案: Dockerfile 以及 start.sh。 Dockerfile 包含構成 Docker 映像檔的宣告行。而 start.sh 是一個基本的 Shell 指令碼,用於建置映像檔並從 Dockerfile 啟動容器。在專案的根目錄中,執行以下命令以建立 Dockerfile:
|
1 |
sudo nano Dockerfile |
此檔案包含 Docker 映像檔所需的設定。接下來,加入以下程式碼片段以指定相依性以及如何建置映像檔:
|
1 2 3 4 5 6 7 8 9 10 11 |
FROM tiangolo/uwsgi-nginx-flask:python3.6-alpine3.7 RUN apk --update add bash nano git ENV STATIC_URL /static ENV STATIC_PATH /var/www/app/static COPY ./dependencies.txt /var/www/dependencies.txt RUN pip install -r /var/www/dependencies.txt |
中的第一行Dockerfile 定義了我們用來構建映像檔的基礎映像檔。在這種情況下,我們將基於 tiangolo/uwsgi-nginx-flask,可從 DockerHub 取得。我們選擇這個特定的映像檔是因為它支援許多 Python 版本。
我們還指定了要更新映像檔。然後,我們需要添加 bash 指令 processo、 nano 文字 編輯器,以及 git 用戶端,用於從版本控制存放庫(例如 )拉取和推送原始碼GitHub, Bitbucket, 或 Gitlab。帶有 ENV 指定要在容器中使用的環境變數。
The COPY 指令將依賴項複製到容器中。 RUN 指令會調用 pip 套件 管理員 來解析 dependencies.txt 檔案並 安裝 這些依賴項。編輯完成後,儲存並關閉檔案。
接下來,您將建立 start.sh 腳本。此腳本將包含 Docker 指令來 構建 和 運行 該映像檔。雖然您可以在終端機上逐步執行這些指令,但我們認為將它們添加到 Shell 腳本中,並只需在終端機中用一個指令調用它會更乾淨。
在定義此檔案的內容之前,我們必須先確定一個其他服務未使用的空閒連接埠。我們將使用連接埠 45644。不過,您可以選擇不同的連接埠。執行以下行以檢查該連接埠是否空閒:
|
1 |
sudo nc localhost 45644 < /dev/null; echo $? |
根據您選擇的連接埠,如果上述指令的輸出為 1,那麼它就是空閒的。否則,您可能必須選擇另一個連接埠並再次嘗試該指令:

既然我們已經確定了一個空閒連接埠,我們現在可以透過運行以下指令,在專案的根目錄中使用 nano 建立該檔案:
|
1 |
sudo nano start.sh |
在此檔案中,添加以下程式碼片段:
|
1 2 3 4 5 6 7 |
#!/bin/bash app_name="docker-flask-demo" docker build -t ${app_name} . docker run -d -p 45644:80 --name=${app_name} -v $PWD:/app ${app_name} |
第一行,被稱為 shebang,指定這是一個 bash 檔案,應作為指令執行。第二行宣告了一個名為 app_name 的變數。我們使用此變數來設定映像檔和容器名稱。第三行指示 Docker 構建 基於當前目錄中 Dockerfile 定義的映像檔。該映像檔將根據變數命名為 docker-flask-demo。
最後一行建立了一個名為 docker-flask-demo,如我們定義的變數所示。 -d 旗標使容器在指令執行完畢後,以分離狀態在背景繼續運行。 -p 旗標將伺服器上的連接埠綁定到容器上的特定連接埠。在這種情況下,我們將主機上的連接埠 45644 掛載到 Docker 將在容器中公開的連接埠 80。
我們使用 -v 旗標來指定要掛載到容器上的 Docker 磁碟區。 $PWD 變數是一個預設的 Linux 變數,保存您在特定時間所在的 目前目錄 的路徑:

在我們的案例中,我們將整個專案目錄掛載到容器的 /var/www 目錄。Docker 設定現在已準備就緒。您可以透過執行以下指令,基於構建的映像檔來構建映像檔並啟動容器:
|
1 |
sudo bash start.sh |
等待腳本運行完畢,然後執行以下 Docker 命令以列出所有運行中的容器:
|
1 |
sudo docker ps |
輸出將顯示運行中的容器:

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

如果您在瀏覽器中看到上述內容,則表示您已成功部署 Flask 應用程式。接下來,我們將修改檔案並透過範本向使用者提供內容。
步驟 3:透過範本檔案提供內容
在 Flask 中,範本 用於向網站訪客顯示靜態和動態內容。我們將向您展示如何建立一個 HTML 範本,並在使用者造訪特定路由時將其提供給他們。例如,這可以是首頁或「關於」頁面。
在您的終端機上執行以下命令,以在 index.html 檔案建立於 app/templates 目錄中:
|
1 |
sudo nano app/templates/index.html |
然後,將以下程式碼片段新增至該檔案:
|
1 2 3 4 5 6 7 8 9 10 11 12 |
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Flask 示範</title> </head> <body> <h2>您在首頁</h2> <p>歡迎來到 此Flask 與 Docker 示範頁面</p> </body> </html> |
完成後儲存並關閉檔案。此外,使用以下命令建立另一個頁面,我們稱之為「關於」頁面:
|
1 |
sudo nano app/templates/about.html |
將以下程式碼片段新增至該檔案:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>關於 Flask 示範</title> </head> <body> <h2>關於頁面</h2> <p>這 是 一個 示範專案. 它展示了如何使用 建置 一個 Flask 應用程式與 Docker 和 Nginx.</p> <p>您可以新增如同 許多頁面和 檔案一樣 您喜歡</p> </body> </html> |
完成後儲存並關閉檔案。接下來,修改 app/views.py 檔案以引用範本以及實際頁面的路由:
|
1 |
sudo nano app/views.py |
修改檔案,使其看起來像這樣:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
from flask import render_template from app import app @app.route('/') def home(): return "我們的 Flask 應用程式正在運行!" @app.route('/index') def index(): return render_template('index.html') @app.route('/about') def about(): return render_template('about.html') |
完成後儲存並關閉檔案。您所做的變更在停止並重新啟動容器之前不會生效。執行以下 Docker 指令來停止和啟動容器。請注意我們之前定義的容器名稱:
|
1 |
sudo docker stop docker-flask-demo && sudo docker start docker-flask-demo |
容器啟動並運行後,造訪首頁和關於頁面以查看一些新內容:
|
1 |
首頁 頁面: http://your-server-public-ip:45644/index |

|
1 |
關於 頁面: http://your-server-public-ip:45644/about |

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

您可能已經注意到,我們必須重新啟動 Docker 容器才能套用新的變更。在下一步中,我們將使其自動化,以確保減少停機時間。
步驟 4:設定應用程式檔案更新以自動重新載入
我們經常會對應用程式進行變更,以改進邏輯、使用者介面或新增一些依賴項。為了使這些變更生效,可能需要您重新啟動 Docker 容器。幸運的是, uWSGI 具有一個名為 touch-reload 的功能,用於在不重新啟動容器的情況下重新載入 Python 指令碼。
開箱即用,Python 具有一個 auto-reloading 功能,它會監視整個檔案系統的變更,並在發生變更時重新整理應用程式。雖然自動重新載入有利於減少停機時間,但它可能會消耗大量資源。因此,不建議在生產環境中使用。
讓我們看看如何使用 touch-reload 來監視特定檔案的變更,並在發生變更時重新載入應用程式。使用 nano 編輯器修改 uwsgi.ini 檔案:
|
1 |
sudo nano uwsgi.ini |
新增醒目提示的行,使其看起來像這樣:
|
1 2 3 4 5 |
[uwsgi] module = main callable = app master = true touch-reload = /app/uwsgi.ini |
完成後儲存並關閉檔案。新增的行指定了一個檔案,修改該檔案將觸發應用程式的重新載入。但是,為了使此條件在未來的修改中生效,您必須先重新啟動容器:
|
1 |
sudo docker stop docker-flask-demo && sudo docker start docker-flask-demo |
您現在可以修改 app/views.py 檔案以示範自動重新載入的工作原理:
|
1 |
sudo nano app/views.py |
將 home 函數傳回的字串變更為醒目提示的內容:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
from flask import render_template from app import app @app.route('/') def home(): return "<h3>Some changes to Our Flask application to auto reload!</h3>" @app.route('/index') def index(): return render_template('index.html') @app.route('/about') def about(): return render_template('about.html') |
完成後儲存並關閉檔案。
在瀏覽器中開啟應用程式的首頁: http://your-server-public-ip:45644.
您還不會看到任何變更。這是因為 touch-reload 條件偵測的是對 uwsgi.ini 檔案的變更。您可以使用 touch 來啟用該條件,從而使用以下指令重新載入整個應用程式:
|
1 |
sudo touch uwsgi.ini |
現在,如果您重新載入首頁,您將會看到顯示的新變更:

未來,如果您進行任何變更,只需執行以下指令 sudo touch uwsgi.ini ,整個應用程式將以更短的停機時間重新載入。本教學到此結束。
結論
在本教學中,您使用 Docker 映像檔和容器實作並部署了一個 Flask 應用程式。為了透過避免重新啟動容器來減少停機時間,您設定了 touch-reload 來監聽特定檔案的變更,並自動重新載入整個應用程式。最後,您在瀏覽器中測試了所有這些功能,以確保其正常運作。
Docker 可確保更快的部署,並允許輕鬆擴充應用程式。如果您想了解更多關於各種 Docker 指令的資訊,請參閱這篇關於 如何在 Ubuntu 上安裝和使用 Docker.
如需更多關於 Docker 的資源,請造訪 我們的部落格,您可以參考以下內容:
- 容器化技術:CloudSigma PaaS 平台上不同容器的類型與用途
- 如何在 Docker 容器與主機之間共享資料
- 在 CentOS 7 上安裝與設定 Docker
- 使用 Docker Compose 部署 Laravel、Nginx 和 MySQL
- 清理 Docker 資源 – 映像檔、容器與資料卷
祝您運算愉快!
留言
目前尚無留言。成為第一個留言的人吧。