單元 4:使用 Docker 從 Google App Engine 遷移至 Cloud Run

1. 總覽

本系列的程式碼研究室 (自助教學和實作教學課程) 旨在引導 Google App Engine (Standard) 開發人員透過一系列遷移作業,協助他們翻新自家應用程式。完成上述作業後,使用者就能針對 Cloud Run、Google Cloud 的容器託管姊妹服務、App Engine 和其他容器託管服務,明確地將應用程式容器化,提高應用程式的可攜性

本教學課程說明如何使用 Docker 將 App Engine 應用程式容器化,以便部署到 Cloud Run 全代管服務。Docker 是業界常見的平台,用於在容器中開發、傳送及執行應用程式。如果是 Python 2 開發人員,本教學課程會從模組 2 的 Cloud NDB 的 App Engine 範例應用程式開始,Python 3 開發人員則會從單元 3 Cloud Datastore 範例開始。

你將瞭解如何

  • 使用 Docker 將應用程式容器化
  • 將容器映像檔部署至 Cloud Run

軟硬體需求

問卷調查

您會如何使用本程式碼研究室?

只能閱讀 閱讀並完成練習

2. 背景

App Engine 和 Cloud Functions 等 PaaS 系統為您的團隊和應用程式提供許多便利性。例如,這些無伺服器平台可讓 SysAdmin/DevOps 專注於建構解決方案。您的應用程式可以視需要自動調度資源,使用即付即用的計費模式將資源縮減至零,同時控管成本,而且會使用多種常見的開發語言。

不過,容器也有彈性,而且能選擇任何語言、程式庫和二進位檔。Google Cloud Run 就是為使用者帶來雙贏的局面、無伺服器的便利性和容器的靈活彈性。

瞭解如何使用 Cloud Run 不在本程式碼研究室的範圍內。請參閱 Cloud Run 說明文件。這個步驟的目的是讓您瞭解如何為 Cloud Run (或其他服務) 將 App Engine 應用程式容器化。繼續前,您需要瞭解一些注意事項,主要是因為您的使用者體驗會略有不同,而且您不再接受應用程式程式碼並進行部署,所以您的使用者體驗會略有不同。

您必須學習容器的一些知識,例如建構及部署容器。您也可以決定要將哪些內容放入容器映像檔,包括網路伺服器,因為您之後不會再使用 App Engine 的網路伺服器。如果您不想依循這個路徑,則建議將應用程式保留在 App Engine 上。

在這個教學課程中,您會瞭解如何將應用程式容器化、使用容器設定取代 App Engine 設定檔、決定容器要傳入什麼內容,以及指定啟動應用程式的方式 (其中許多作業會自動由 App Engine 自動處理)。

這項遷移作業包含下列步驟:

  1. 設定/事前作業
  2. 將應用程式
      容器化
    • 取代設定檔
    • 修改應用程式檔案

3. 設定/事前作業

在開始教學課程的主要部分之前,我們先設定專案、取得程式碼,然後部署基準應用程式,以便瞭解要開始使用有效的程式碼。

1. 設定專案

如果您已完成單元 2單元 3 的程式碼研究室,建議您重複使用相同的專案 (和程式碼)。或者,您可以建立新的專案,或是重複使用其他現有專案。請確認專案具備有效的帳單帳戶,且 App Engine (應用程式) 已啟用。

2. 取得基準範例應用程式

使用本程式碼研究室的必要條件之一,是擁有正常運作的模組 2 或模組 3 範例應用程式。如果您沒有課程,請先完成任一教學課程 (上方的連結),再繼續操作。如果您熟悉其中的內容,可以直接擷取下方的單元 2 或 3 程式碼。

無論您使用您自己的還是我們的,單元 2 程式碼都會在我們的教學課程中開始 Python 2 版本,同樣的道理,Python 3 的模組 3 程式碼也同樣適用。本單元單元 4 會逐步引導您完成每個步驟,完成後,您的最終程式碼應會在完成時類似模組 4 存放區資料夾 (FINISH) 的其中一個程式碼。

Python 2 單元 2 START 的目錄 (您或我們的檔案) 應如下所示:

$ ls
README.md               appengine_config.py     requirements.txt
app.yaml                main.py                 templates

如果使用自己的模組 2 (2.x) 程式碼,也會有 lib 資料夾。Python 3 不會使用 libappengine_config.py,其中模組 3 (3.x) 開始程式碼應如下所示:

$ ls
README.md               main.py                 templates
app.yaml                requirements.txt

3. (重新) 部署基準應用程式

您目前需執行的準備作業步驟:

  1. 請重新熟悉 gcloud 指令列工具。
  2. 使用 gcloud app deploy 重新部署範例應用程式
  3. 確認應用程式在 App Engine 上執行,沒有問題

成功執行這些步驟後,就可以將步驟容器化。

4. 將應用程式容器化

Docker 是現今產業的標準容器化平台。如前所述,使用容器的其中一項挑戰是必須控管高效的 Dockerfile,也就是決定容器映像檔建構方式的設定檔。Buildpacks 則是利用自我檢查功能判斷應用程式的依附元件,因此幾乎不需要耗費太多心力,因此建構套件容器能為應用程式盡可能提高效率。

如果您已瞭解容器和 Docker,而且想進一步瞭解如何針對 Cloud Run 將 App Engine 應用程式容器化,這裡會是合適的選擇。之後如有需要,也歡迎進行單元 5 程式碼研究室 (與本程式碼研究室相同,但使用 Cloud Buildpacks)。我們的基本應用程式範例十分輕巧,可避免上述某些 Dockerfile 問題。

遷移步驟包括替換 App Engine 設定檔,以及指定應用程式的啟動方式。下表摘要列出各種平台類型適用的設定檔。比較 App Engine 資料欄與 Docker 資料欄 (以及選用的 Buildpacks):

說明

App Engine

Docker

建築包

一般設定

app.yaml

Dockerfile

(service.yaml)

第三方程式庫

requirements.txt

requirements.txt

requirements.txt

第三方設定

app.yaml (加上 appengine_config.pylib [2.x-only])

(不適用)

(不適用)

啟動

(不適用)app.yaml (如果使用 entrypoint)

Dockerfile

Procfile

忽略檔案

.gcloudignore.gitignore

.gcloudignore.gitignore.dockerignore

.gcloudignore.gitignore

應用程式容器化後,即可部署至 Cloud Run。其他 Google Cloud 容器平台選項包括 Compute EngineGKEAnthos

一般設定

從 App Engine 遷移是指將 app.yaml 替換為概述如何建構及執行容器的 Dockerfile。App Engine 會自動啟動您的應用程式,但 Cloud Run 不會。這就是 Dockerfile ENTRYPOINTCMD 指令的用途。如要進一步瞭解 Dockerfile,請參閱這個 Cloud Run 說明文件頁面,並查看產生 gunicornDockerfile 範例。

除了在 Dockerfile 中使用 ENTRYPOINTCMD,您也可以改用 Procfile。最後,.dockerignore 可協助篩除非應用程式檔案,將容器大小縮減。即將推出更多內容!

刪除「app.yaml」並建立「Dockerfile

容器中未使用 app.yaml,因此立即刪除。容器設定檔為 Dockerfile,而我們的範例應用程式只需要最少一個。視您使用的 Python 版本而定,使用此內容建立 Dockerfile,並將 NNN 替換為 23

FROM python:NNN-slim
WORKDIR /app
COPY . .
RUN pip install -r requirements.txt
ENTRYPOINT ["python", "main.py"]

大部分的 Dockerfile 都會指定如何建立容器,但「除了」ENTRYPOINT 會指定如何「啟動」容器;在此例中,請呼叫 python main.py 來執行 Flask 開發伺服器。如果您是第一次使用 Docker,FROM 指令會指出起始的基本映像檔、「精簡」是指最小的 Python 發行版詳情請參閱 Docker Python 映像檔頁面

中間的指令會建立工作目錄 (/app)、複製到應用程式檔案中,然後執行 pip install,將第三方程式庫導入容器。WORKDIR 結合了 Linux mkdircd 指令;詳情請參閱 WORKDIR 說明文件 COPYRUN 指令都很簡單明瞭。

第三方程式庫

requirements.txt 檔案可以維持不變;Flask 應該會與 Datastore 用戶端程式庫 (Cloud Datastore 或 Cloud NDB) 一起出現。如果您想使用其他符合 WSGI 規定的 HTTP 伺服器 (例如 Gunicorn),截至本文撰寫時使用的是 20.0.4 版本,請將 gunicorn==20.0.4 新增至 requirements.txt

第三方設定

Python 2 App Engine 開發人員知道第三方程式庫必須複製到 requirements.txt 中參照的 lib 資料夾,在 app.yaml 中逐一列出,並且由 appengine_config.py 提供支援。容器 (例如 Python 3 App Engine 應用程式) 只能使用 requirements.txt,因此所有其他內容都可能遭到捨棄。也就是說,如果您有 2.x App Engine 應用程式,請刪除 appengine_config.py 和任何 lib 資料夾。

啟動

Python 2 使用者不會啟動 App Engine 的網路伺服器,但在移至容器時,您必須執行這個步驟。方法是在 Dockerfile 中新增 CMDENTRYPOINT 指令,以指定應用程式啟動方式。下文所述的方式與 Python 3 使用者相同。

Python 3 使用者可選擇將 app.yaml 檔案轉換為 handlers 區段的 entrypoint,而非 script: auto 指令。如果您在 Python 3 app.yaml 中使用 entrypoint,則看起來會像這樣:

runtime: python38
entrypoint: python main.py

entrypoint 指令會指示 App Engine 如何啟動您的伺服器。您可以幾乎可直接將其移至 Dockerfile 中 (如果使用 Buildpacks 來建構應用程式,則為 Procfile)。總結在兩個平台之間進入進入點指令的位置:

  • Docker:Dockerfile 中的行:ENTRYPOINT ["python", "main.py"]
  • 建構套件:Procfile 中的行:web: python main.py

使用 Flask 開發伺服器即可進行測試,但如果應用程式使用 gunicorn 等正式版伺服器,請務必按照 Cloud Run 快速入門導覽課程範例中的說明,將 ENTRYPOINTCMD 指令指向該伺服器。

忽略檔案

建議您建立 .dockerignore 檔案來縮減容器大小,同時避免使用下列多餘檔案,讓容器映像檔過於雜亂:

*.md
*.pyc
*.pyo
.git/
.gitignore
__pycache__

應用程式檔案

所有模組 2 或模組 3 應用程式均與 Python 2 至 3 完全相容,這表示 main.py 的核心元件沒有變更。您只需要新增幾行啟動程式碼即可在 main.py 底部加入幾行指令來啟動開發伺服器,因為 Cloud Run 需要先開啟通訊埠 8080,才能呼叫您的應用程式:

if __name__ == '__main__':
    import os
    app.run(debug=True, threaded=True, host='0.0.0.0',
            port=int(os.environ.get('PORT', 8080)))

5. 建構及部署

完成 Docker 設定和來源檔案更新後,即可開始在 Cloud Run 中執行。在此之前,先簡單介紹服務

服務與應用程式

雖然 App Engine 主要是用來託管應用程式,但這個平台也用於託管一組微服務或應用程式的網路服務或應用程式。在 Cloud Run 中,「所有」都是服務,無論是實際服務還是具有網頁介面的應用程式,所以請考慮將其視為服務的部署,而非應用程式。

除非您的 App Engine 應用程式是由多項服務組成,否則部署應用程式時,您確實不需要命名任何類型。而必須藉由 Cloud Run 設定「服務名稱」,才能使變更生效。雖然 App Engine 的 appspot.com 網域會提供專案 ID,例如https://PROJECT_ID.appspot.com,也許是區域 ID 縮寫,例如http://PROJECT_ID.REGION_ID.r.appspot.com

不過,Cloud Run 服務的網域會有服務名稱、區域 ID 縮寫和雜湊,但不含專案 ID (例如跳到 https://SVC_NAME-HASH-REG_ABBR.a.run.app 的位置。最後,先想想服務名稱!

部署服務

執行下列指令,建構容器映像檔並部署至 Cloud Run。系統提示時,請選取您的區域並允許未經驗證的連線,以便簡化測試;視情況選取區域,其中 SVC_NAME 是您要部署的服務名稱。

$ gcloud beta run deploy SVC_NAME --source .
Please choose a target platform:
 [1] Cloud Run (fully managed)
 [2] Cloud Run for Anthos deployed on Google Cloud
 [3] Cloud Run for Anthos deployed on VMware
 [4] cancel
Please enter your numeric choice:  1

To specify the platform yourself, pass `--platform managed`. Or, to make this the default target platform, run `gcloud config set run/platform managed`.

Please specify a region:
 [1] asia-east1
 [2] asia-east2
 [3] asia-northeast1
 [4] asia-northeast2
 [5] asia-northeast3
 [6] asia-south1
 [7] asia-southeast1
 [8] asia-southeast2
 [9] australia-southeast1
 [10] europe-north1
 [11] europe-west1
 [12] europe-west2
 [13] europe-west3
 [14] europe-west4
 [15] europe-west6
 [16] northamerica-northeast1
 [17] southamerica-east1
 [18] us-central1
 [19] us-east1
 [20] us-east4
 [21] us-west1
 [22] us-west2
 [23] us-west3
 [24] us-west4
 [25] cancel
Please enter your numeric choice: <select your numeric region choice>

To make this the default region, run `gcloud config set run/region REGION`.

Allow unauthenticated invocations to [SVC_NAME] (y/N)?  y

Building using Dockerfile and deploying container to Cloud Run service [SVC_NAME] in project [PROJECT_ID] region [REGION]
✓ Building and deploying new service... Done.
  ✓ Uploading sources...
  ✓ Building Container... Logs are available at [https://console.cloud.google.com/cloud-build/builds/BUILD-HASH?project=PROJECT_NUM].
  ✓ Creating Revision... Deploying Revision.
  ✓ Routing traffic...
  ✓ Setting IAM Policy...
Done.
Service [SVC_NAME] revision [SVC_NAME-00001-vos] has been deployed and is serving 100 percent of traffic.
Service URL: https://SVC_NAME-HASH-REG_ABBR.a.run.app

使用瀏覽器造訪指定網址,確認部署成功!

正如 gcloud 指令所示,使用者可以設定各種預設設定以減少輸出和互動次數,如上所示。舉例來說,如要避免所有互動,您可以改用下列單行部署指令:

$ gcloud beta run deploy SVC_NAME --source . --platform managed --region REGION --allow-unauthenticated

如果使用這個方法,請務必選取相同的服務名稱 SVC_NAME 和所需的 REGION 名稱,而非已建立索引的選單選項 (與先前互動的操作方式不同)。

6. 摘要/清除

確認應用程式在 Cloud Run 中的運作方式與 App Engine 相同。如果您進入本系列課程,但未執行先前的任何程式碼研究室,應用程式本身並不會改變。它會記錄主網頁 (/) 的所有造訪,而且在您造訪此網站足夠的時間後看起來像下面這樣:

Visitme 應用程式

您的程式碼現在應與模組 4 存放區資料夾的內容相符,無論是 2.x3.x 都一樣。恭喜您完成單元 4 程式碼研究室。

選用:清除

在準備進入下一個遷移程式碼研究室之前,您該如何清除所用資源,以免產生費用?由於現在使用的是其他產品,請務必詳閱 Cloud Run 定價指南

選用:停用服務

如果還不想進行下一個教學課程,請停用服務,以免產生額外費用。當您準備好前往下一個程式碼研究室時,即可重新啟用。停用的應用程式不會獲得任何流量,不過如果用量超過免費配額,我們就會向您收取 Datastore 用量的費用,因此刪除費用就會低於配額上限。

另一方面,如果您不想繼續進行遷移作業,想要徹底刪除所有資料,可以選擇刪除服務或完全關閉專案

後續步驟

恭喜,您已經容器化應用程式,教學課程到此結束!下一步就是在單元 5 程式碼研究室 (如下連結) 中,瞭解如何使用 Cloud Buildpacks 執行相同作業,或是進行其他 App Engine 遷移作業:

  • 如果您尚未遷移至 Python 3,請先完成這項作業。這個範例應用程式已經與 2.x 和 3.x 相容,因此唯一的改變是讓 Docker 使用者更新 Dockerfile,以便使用 Python 3 映像檔。
  • 單元 5:遷移至 Cloud Run 與 Cloud Buildpacks
    • 將應用程式容器化,讓應用程式透過 Cloud Buildpacks 在 Cloud Run 中執行
    • 您不必瞭解任何 Docker、容器或 Dockerfile 的內容
    • 您需要將應用程式遷移至 Python 3
  • 單元 7:App Engine 推送工作佇列 (如果您使用 [push] 工作佇列,則為必要項目)
    • 將 App Engine taskqueue 推送工作新增至模組 1 應用程式
    • 協助使用者做好準備,以便遷移至 Cloud Tasks
  • 單元 3:
    • 翻新從 Cloud NDB 存取 Cloud Datastore 的 Datastore 存取權
    • 這是 Python 3 的 App Engine 應用程式和非 App Engine 應用程式所使用的程式庫。
  • 模組 6:遷移至 Cloud Firestore
    • 遷移至 Cloud Firestore 即可使用 Firebase 功能
    • Cloud Firestore 支援 Python 2,但本程式碼研究室僅適用於 Python 3。

7. 其他資源

App Engine 遷移模組程式碼研究室問題/意見回饋

如果您在本程式碼研究室中發現任何問題,請先搜尋您的問題再提出申請。搜尋及建立新問題的連結:

遷移資源

下表提供模組 2 和 3 (START) 和單元 4 (FINISH) 的存放區資料夾連結。您也可以透過所有 App Engine 程式碼研究室遷移作業的存放區存取這些資料,可以複製或下載 ZIP 檔案。

Codelab

Python 2

Python 3

Module 2

程式碼

(程式碼)

Module 3

(程式碼)

程式碼

Module 4

程式碼

程式碼

App Engine 和 Cloud Run 資源

以下是這項特定遷移作業的其他資源: