模块 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,libappengine_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.pylib [仅限 2.x])

(不适用)

(不适用)

启动

(不适用)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 命令的用途。从此 Cloud Run 文档页面中详细了解 Dockerfile,并查看生成 gunicorn 的示例 Dockerfile

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

删除 app.yaml 并创建 Dockerfile

未在容器中使用 app.yaml,因此请立即删除。容器配置文件为 Dockerfile,我们的示例应用只需满足最低要求。使用以下内容创建 Dockerfile,并将 NNN 替换为 23,具体取决于您使用的 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 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 开发者知道,第三方库复制到 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 中添加 CMDENTRYPOINT 指令来指定如何启动应用来完成的,下面以与 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 这样的生产服务器,请确保将 ENTRYPOINTCMD 指令指向它,像在 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 资源

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