模块 4:使用 Docker 从 Google App Engine 迁移到 Cloud Run

这一系列的 Codelab(自定进度的动手教程)旨在帮助 Google App Engine(标准)开发者通过一系列迁移来指导他们的应用现代化。完成此操作后,用户可以通过将其显式容器化以支持 Cloud Run,App Engine 的 Google Cloud 容器托管姊妹服务以及其他容器托管服务,从而使其应用更具可移植性。

本教程教您如何容器化 App Engine 应用,以使用 Docker 部署到 Cloud Run 全代管式服务,Docker 是业界知名的平台,用于在容器中开发、运输和运行应用。对于 Python 2 开发者,本教程从模块 2 Cloud NDB App Engine 示例应用开始,而 Python 3 开发人员从模块 3 Cloud Datastore 示例开始。

您将了解如何

  • 使用 Docker 将应用容器化
  • 将容器映像部署到 Cloud Run

所需条件

调查问卷

如何使用此 Codelab?

只是阅读 阅读并完成练习

PaaS 系统(例如 App Engine 和 Cloud Functions)为您的团队和应用提供了许多便利。例如,这些无服务器平台,可让 SysAdmin/Devops 重点打造解决方案。您的应用可根据需要自动扩缩,使用按用量计费的结算方式有助于缩减至零,并使用多种常见的开发语言。

不过,容器的灵活性也具有吸引力,能够选择任何语言、任何库、任何二进制文件。Google Cloud Run 的宗旨就是为用户提供两全其美的体验、无服务器的便利性以及容器的灵活性。

了解如何使用 Cloud Run 不在本 Codelab 的范围之内,而是在 Cloud Run 文档中介绍。这里的目标是让您知道如何为 Cloud Run(或其他服务)容器化 App Engine 应用。在继续前进之前,您需要了解一些事项,主要是您的用户体验会略有不同,因为您将不再使用应用代码进行部署,因此用户体验会稍低一些。

相反,您需要学习一些有关容器的知识,例如如何构建和部署它们。您还可以决定要在容器映像中放入什么,包括网络服务器,因为您将不再使用 App Engine 的网络服务器。如果您不想遵循此路径,那么将应用保持在 App Engine 上并不是一个坏选择。

在本教程中,您将学习如何对应用进行容器化,用容器配置替换 App Engine 配置文件,确定将哪些内容放入容器中,然后指定如何启动应用,其中许多事项都是由 App Engine 自动处理。

此迁移具有以下步骤:

  1. 设置/准备工作
  2. 容器化应用
    • 替换配置文件
    • 修改应用文件

在开始学习本教程的主要部分之前,让我们设置项目、获取代码,然后部署基准应用,以便我们知道我们从工作代码开始。

1.设置项目

如果您完成了模块 2 或模块 3 的 Codelab,我们建议重复使用同一项目(和代码)。或者,您可以创建一个全新的项目或重复使用另一个现有项目。确保该项目具有有效的结算帐号,并且已启用 App Engine(应用)。

2.获取基准示例应用

此 Codelab 的先决条件之一是拥有一个工作正常的模块 2 或模块 3 示例应用。如果您没有,请先完成其中一个教程(上面的链接),然后再继续学习。否则,如果您已经熟悉其内容,则可以从下面的模块 2 或 3 代码开始。

无论您使用的是本教程,还是本教程的 Python 2 版本,我们都将在这里开始使用模块 2 代码,而在 Python 3 中,则类似地使用模块 3 代码。这个模块 4 Codelab 将引导您完成每个步骤,并且根据您的选择,最终应该获得类似于模块 4 代码库文件夹 (FINISH) 之一的代码。

Python 2 模块 2 启动文件(您或我们的文件)的目录应如下所示:

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

如果您使用的是自己的模块 2 (2.x) 代码,那么还会有一个 lib 文件夹。对于 Python 3,lib 和 appengine_config.py 均不适用,其中模块 3 (3.x) START 代码如下所示:

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

3.(重新)部署基准应用

现在,您需要执行剩余的准备工作步骤:

  1. 重新熟悉 gcloud 命令行工具
  2. 使用 gcloud app deploy 重新部署示例应用
  3. 确认应用在 App Engine 上运行没有任何问题

成功执行完这些步骤后,您就可以对其进行容器化。

Docker 是当今行业的标准容器化平台。如上所述,使用该工具的一个挑战是需要投入有效的 Dockerfile,此配置文件确定容器映像的构建方式。另一方面,Buildpack 不需要花费太多精力,因为它使用内检来确定应用的依赖关系,从而使 Buildpack 容器对您的应用尽可能有效。

如果您已经对容器和 Docker 有所了解,并且想要了解有关为 Cloud Run 容器化 App Engine 应用的更多信息,那么您来对地方了。之后,您还可以随意使用模块 5 Codelab(与本模块相同,但增加了 Cloud Buildpack)。我们的准系统示例应用足够轻巧,可以避免某些上述 Dockerfile 问题。

迁移步骤包括替换 App Engine 配置文件以及指定应如何启动应用。下表总结了每种平台类型所需的配置文件。将 App Engine 列与 Docker 列(以及可选的 Buildpack)进行比较:

说明

App Engine

Docker

Buildpack

常规配置

app.yaml

Dockerfile

(service.yaml)

第三方库

requirements.txt

requirements.txt

requirements.txt

第三方配置

app.yaml(以及 appengine_config.py 和 lib [仅限 2.x])

(不适用)

(不适用)

启动

(不适用)或 app.yaml(如果使用 entrypoint)

Dockerfile

Procfile

忽略文件

.gcloudignore 和 .gitignore

.gcloudignore、.gitignore 和 .dockerignore

.gcloudignore 和 .gitignore

将您的应用容器化后,就可以将其部署到 Cloud Run。其他 Google Cloud 容器平台选项包括 Compute Engine、GKE 和 Anthos。

常规配置

从 App Engine 迁移意味着将 app.yaml 替换为概述如何构建和运行容器的 Dockerfile。App Engine 自动启动您的应用,但 Cloud Run 不会。Dockerfile ENTRYPOINT 和 CMD 命令的用途。从此 Cloud Run 文档页面中详细了解 Dockerfile,并查看生成 gunicorn 的示例 Dockerfile。

在 Dockerfile 中使用 ENTRYPOINT 或 CMD 的替代方案是使用 Procfile。最后,.dockerignore 有助于过滤掉非应用文件,以减小容器大小。即将发布更多内容!

删除 app.yaml 并创建 Dockerfile

未在容器中使用 app.yaml,因此请立即删除。容器配置文件为 Dockerfile,我们的示例应用只需满足最低要求。使用以下内容创建 Dockerfile,并将 NNN 替换为 2 或 3,具体取决于您使用的 Python 版本:

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 指令指示从其开始的基本映像,而“slim”则是指最小的 Python 发行版。如需了解详情,请参阅 Docker Python 映像页面。

这组命令会创建工作目录 (/app),接着复制应用文件,然后运行 pip install 以将第三方库放入容器中。WORKDIR 将 Linux mkdir 和 cd 命令组合在一起;如需了解详情,请参阅 WORKDIR 文档。COPY 和 RUN 指令的含义不言自明。

第三方库

requirements.txt 文件可以保持不变;Flask 连同 Datastore 客户端库(Cloud Datastore 或 Cloud NDB)一起提供。如果您希望使用其他兼容 WSGI 的 HTTP 服务器(例如 Gunicorn,编写文档时的最新版本为 20.0.4),请将 gunicorn==20.0.4 添加到 requirements.txt。

第三方配置

Python 2 App Engine 开发者知道,第三方库复制到 lib 文件夹中、在 requirements.txt 中引用、在 app.yaml 中逐项列出以及受 appengine_config.py 支持。与 Python 3 App Engine 应用一样,容器仅使用 requirements.txt,因此所有其他项都可以删除,这意味着如果您拥有 2.x App Engine 应用,请删除 appengine_config.py 以及任何 lib 文件夹。

启动

Python 2 用户不会启动 App Engine 的网络服务器,但是当移至容器时,您必须这样做。这是通过在 Dockerfile 中添加 CMD 或 ENTRYPOINT 指令来指定如何启动应用来完成的,下面以与 Python 3 用户相同的方式进行说明。

Python 3 用户可以选择在其 handlers 部分将其 app.yaml 文件转换为具有 entrypoint 而不是 script: auto 指令。如果您在 Python 3 app.yaml 中使用 entrypoint,它将看起来像这样:

runtime: python38
entrypoint: python main.py

entrypoint 指令告知 App Engine 如何启动服务器。您几乎可以将其直接移到 Dockerfile 中(如果使用 Buildpack,则为 Procfile [请参阅模块 5])以容器化应用。汇总 entrypoint 指令在两个平台之间的位置:

  • Docker:Dockerfile 中的行:ENTRYPOINT ["python", "main.py"]
  • Buildpack:Procfile 中的行:web: python main.py

使用 Flask 开发服务器可以很好地进行测试,但是如果在您的应用中使用像 gunicorn 这样的生产服务器,请确保将 ENTRYPOINT 或 CMD 指令指向它,像在 Cloud Run 快速入门示例中一样。

忽略文件

我们建议创建一个 .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)))

完成 Docker 配置和源文件更新后,您就可以在 Cloud Run 上运行该模型了。在此之前,我们先简要讨论服务。

服务与应用

虽然 App Engine 最初是为托管应用而创建的,但它还是一个托管由微服务集合组成的 Web 服务或应用的平台。在 Cloud Run 中,一切都是服务,无论是实际服务还是具有 Web 界面的应用,因此请考虑将其用作服务的部署而不是应用。

除非您的 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

如果您使用此 API,请务必提供相同的服务名称 SVC_NAME 和所需的 REGION 名称,而不是已编入索引的菜单选项(如上所述)。

确认应用在 Cloud Run 上和在 App Engine 上一样。如果您跳过本系列,但未执行任何上述 Codelab,则应用本身不会更改;它会记录对主网页 (/) 的所有访问,在您访问过该网站后,将如下所示:

visitme 应用

您的代码现在应与模块 4 代码库文件夹中的内容相匹配,无论它是 2.x 还是 3.x。恭喜您完成本模块 4 的 Codelab。

可选:清理

何不准备好清理,以避免在进入下一个迁移 Codelab 时继续计费?由于您目前使用的是其他产品,请务必查看 Cloud Run 价格指南。

可选:停用服务

如果您尚未准备好下一个教程,请停用您的服务,以避免产生额外费用。准备好运行下一个 Codelab 后,可以重新启用它。在您的应用被停用的情况下,它不会获取任何流量来产生费用,但是您还需要计费的另一事项是,如果 Datastore 使用量超出免费配额,因此请删除一部分使用量,以使其低于该限制。

另一方面,如果您不打算继续迁移,并想删除所有内容,则可以删除您的服务或彻底关停项目。

后续步骤

恭喜,您已对应用进行容器化,本教程结束!下一步,您将了解如何在模块 5 的 Codelab 中通过 Cloud Buildpack 执行相同的操作(下面的链接),或学习另一个 App Engine 迁移:

  • 迁移到 Python 3(如果您尚未迁移)。示例应用已兼容 2.x 和 3.x,因此唯一的更改是让 Docker 用户更新其 Dockerfile 以使用 Python 3 映像。
  • 模块 5:使用 Cloud Buildpack 迁移到 Cloud Run
    • 将应用设置为使用 Cloud Buildpack 在 Cloud Run 上运行
    • 您无需了解有关 Docker、容器或 Dockerfile 的任何信息
    • 您需要将应用迁移到 Python 3
  • 模块 7:App Engine 推送任务队列(如果您使用 [推送] 任务队列,此为必需参数)
    • 向模块 1 应用添加 App Engine taskqueue 推送任务
    • 准备用户迁移到模块 8 中的 Cloud Tasks
  • 模块 3:
    • 对从 Cloud NDB 到 Cloud Datastore 的 Datastore 访问进行现代化改造
    • 这是用于 Python 3 App Engine 应用和非 App Engine 应用的库
  • 模块 6:迁移到 Cloud Firestore
    • 迁移到 Cloud Firestore 以使用 Firebase 功能
    • Cloud Firestore 支持 Python 2,但此 Codelab 仅在 Python 3 中可用。

App Engine 迁移模块 Codelab 问题/反馈

如果您遇到此 Codelab 的任何问题,请先搜索您的问题,然后再提交。用于搜索新问题和创建新问题的链接:

迁移资源

下方表格提供了指向模块 2 和模块 3 (START) 以及代码库 4 (FINISH) 的代码库文件夹的链接。您也可以通过所有 App Engine Codelab 迁移的代码库访问这些代码库,该代码库可以克隆或下载 ZIP 文件。

Codelab

Python 2

Python 3

模块 2

代码

(代码)

模块 3

(代码)

代码

模块 4

代码

代码

App Engine 和 Cloud Run 资源

以下是有关此具体迁移的其他资源: