将 Python Flask Web 应用部署到 App Engine 柔性环境

摘要

在此 Codelab 中,您将学习如何将 Python Flask Web 应用部署到 App Engine 柔性环境。此示例应用允许用户上传人脸照片,并了解照片中的人有多大可能感到快乐。该应用使用 Google Cloud API 进行视觉、存储和 Datastore 操作。

关于 App Engine

Google App Engine 应用易于创建、易于维护,并可根据流量和数据存储需求的变化轻松扩缩。使用 App Engine 时,无需维护任何服务器。您只需上传应用,就可以使用了。

App Engine 应用会根据传入的流量自动扩缩。负载均衡、微服务、授权、SQL 和 NoSQL 数据库、流量分配、日志记录、搜索、版本控制、发布和回滚以及安全扫描都是原生支持的,并且高度可自定义。

App Engine 的柔性环境支持以下所有编程语言:C#、Go、Java、Node.js、PHP、Python 和 Ruby。App Engine 柔性环境在 Google Compute Engine 虚拟机上运行的 Docker 容器中运行应用。App Engine 的标准环境是某些语言(包括 Python)的替代选项。App Engine 标准环境会在限制更严格的沙盒环境中运行您的应用。如需了解详情,请参阅选择 App Engine 环境

学习内容

  • 如何将简单的 Web 应用部署到 App Engine 柔性环境
  • 如何访问 Vision、Storage 和 Datastore 的 Google Cloud 客户端库
  • 如何使用 Google Cloud 控制台和 Google Cloud SDK 管理各种云资源
  • 如何使用 Cloud Shell

所需条件

  • 熟悉 Python
  • 熟悉标准的 Linux 文本编辑器,例如 Vim、Emacs 或 Nano

项目创建

如果您还没有 Google 账号(Gmail 或 Google Apps),则必须创建一个。登录 Google Cloud Platform Console (console.cloud.google.com) 并创建一个新项目:

请记住项目 ID,它在所有 Google Cloud 项目中都是唯一的名称(上述名称已被占用,您无法使用,抱歉!)。它稍后将在此 Codelab 中被称为 PROJECT_ID

结算

接下来,您需要在 Cloud Console 中启用结算功能,才能使用 Google Cloud 资源。

在此 Codelab 中运行仅花费几美元,但是如果您决定使用更多资源或继续让它们运行,费用可能更高。

Google Cloud Platform 的新用户有资格获享 $300 免费试用

虽然 Google Cloud 可以从笔记本电脑远程操作,但在此 Codelab 中,我们将使用 Google Cloud Shell,这是一个在云端运行的命令行环境。这个基于 Debian 的虚拟机上已加载您需要的所有开发工具(gcloudpythonvirtualenvpip 等),并提供永久性的 5 GB 主目录。它在 Google Cloud 上运行,可大幅提升网络性能和身份验证。这意味着在本 Codelab 中,您只需要一个浏览器(没错,它适用于 Chromebook)。

如需激活 Google Cloud Shell,只需在开发者控制台中点击右上角的按钮(预配和连接到环境仅需花费一些时间):

在连接到 Cloud Shell 后,您应该会看到自己已通过身份验证,并且相关项目已设置为您的项目 ID:

gcloud auth list
Credentialed accounts:
- <myaccount>@<mydomain>.com (active)
gcloud config list project
[core]
Project = <PROJECT_ID>

如果出于某种原因未设置项目,只需发出以下命令即可:

gcloud config set project <PROJECT_ID>

想查找您的 PROJECT_ID?检查您在设置步骤中使用的项目 ID,或在控制台信息中心查找该 ID:

在 Cloud Shell 的命令行中,运行以下命令以克隆 GitHub 代码库:

git clone https://github.com/GoogleCloudPlatform/python-docs-samples.git

将目录更改为 python-docs-samples/codelabs/flex_and_vision

cd python-docs-samples/codelabs/flex_and_vision

在开始使用 Vision、Storage 和 Datastore API 之前,您必须使用以下命令启用这些 API:

gcloud services enable vision.googleapis.com
gcloud services enable storage-component.googleapis.com
gcloud services enable datastore.googleapis.com

如需向 Vision、Storage 和 Datastore API 发出请求,您需要服务账号凭据。您可以使用 gcloud 工具生成项目中的服务账号凭据。

为您的 PROJECT_ID 设置环境变量,将 [YOUR_PROJECT_ID] 替换为您自己的项目 ID:

export PROJECT_ID=[YOUR_PROJECT_ID]

创建服务账号以在本地测试时访问 Google Cloud API:

gcloud iam service-accounts create codelab \
  --display-name "My Codelab Service Account"

为新创建的服务账号授予适当的权限:

gcloud projects add-iam-policy-binding ${PROJECT_ID} \
--member serviceAccount:codelab@${PROJECT_ID}.iam.gserviceaccount.com \
--role roles/owner

创建服务账号后,请创建服务账号密钥:

gcloud iam service-accounts keys create ~/key.json \
--iam-account codelab@${PROJECT_ID}.iam.gserviceaccount.com

此命令会生成一个服务账号密钥,该密钥存储在主目录中名为 key.json 的 JSON 文件中。

使用生成的密钥的绝对路径,在 Cloud Shell 中为您的服务账号密钥设置环境变量:

export GOOGLE_APPLICATION_CREDENTIALS="/home/${USER}/key.json"

您可以详细了解如何对 Vision API 进行身份验证

启动虚拟环境并安装依赖项

使用 virtualenv 创建一个名为 env 的独立 Python 3 环境:

virtualenv -p python3 env

进入新创建的名为 envvirtualenv

source env/bin/activate

使用 piprequirements.txt 文件中安装项目的依赖项:

pip install -r requirements.txt

requirements.txt 文件是项目所需的软件包依赖项列表。上述命令已将所有列出的软件包依赖项下载到 virtualenv

创建 App Engine 应用

接下来,使用以下命令创建 App Engine 实例:

gcloud app create

创建存储分区

首先,将环境变量 CLOUD_STORAGE_BUCKET 设置为您的 PROJECT_ID 的名称。(一般建议将存储分区命名为与 PROJECT_ID 相同的名称,以便于操作)。

export CLOUD_STORAGE_BUCKET=${PROJECT_ID}

我们的应用使用 Cloud Storage 存储分区,您需要使用名为 gsutil 的工具从 Cloud Shell 创建该存储分区。运行以下命令,该命令会创建一个与您的 PROJECT_ID 同名的存储分区。

gsutil mb gs://${PROJECT_ID}

运行应用

python main.py

应用启动后,点击 Cloud Shell 工具栏中的“网页预览”图标 ,然后选择“在端口 8080 上预览”。

浏览器会打开一个标签页,并连接到您刚启动的服务器。您应该会看到与以下类似的内容:

Screen Shot 2017-02-23 at 7.22.50 PM.png

尝试上传包含人脸的照片。点击选择文件按钮,从计算机中选择一张图片,然后点击提交

上传照片后,您应该会看到类似如下的内容:

Screen Shot 2017-02-23 at 7.32.08 PM.png

示例代码布局

该示例的布局如下:

templates/
  homepage.html   /* HTML template that uses Jinja2 */
app.yaml          /* App Engine application configuration file */
main.py           /* Python Flask web application */
requirements.txt  /* List of dependencies for the project */

main.py

此 Python 文件是一个 Flask Web 应用。该应用允许用户提交照片(最好是人脸照片),这些照片会存储在 Cloud Storage 中,并使用 Cloud Vision API 的人脸检测功能进行分析。每张照片的关键信息都存储在 Datastore(Google Cloud Platform 的 NoSQL 数据库)中,用户每次访问网站时都会访问这些信息。

此应用使用适用于 Storage、Datastore 和 Vision 的 Google Cloud Platform 客户端库。借助这些客户端库,您可以轻松地使用自己偏好的编程语言访问 Cloud API。

我们来看一下代码的一些关键代码段。

顶部的“imports”部分用于导入代码所需的各种软件包。以下是我们如何导入 Datastore、Storage 和 Vision 的 Google Cloud 客户端库:

from google.cloud import datastore
from google.cloud import storage
from google.cloud import vision

以下代码用于指定当用户访问网站的根网址时会发生什么情况。我们创建了一个 Datastore 客户端对象,用于访问 Datastore 客户端库。然后,我们对 Datastore 运行查询,以查找种类为 Faces 的实体。最后,我们呈现 HTML 模板,并将从 Datastore 中提取的 image_entities 作为变量传入。

@app.route('/')
def homepage():
    # Create a Cloud Datastore client.
    datastore_client = datastore.Client()

    # Use the Cloud Datastore client to fetch information from Datastore about
    # each photo.
    query = datastore_client.query(kind='Faces')
    image_entities = list(query.fetch())

    # Return a Jinja2 HTML template and pass in image_entities as a parameter.
    return render_template('homepage.html', image_entities=image_entities)

我们来看看如何将实体保存到 Datastore 中。Datastore 是 Google Cloud 的 NoSQL 数据库解决方案。数据存储在称为实体的对象中。每个实体都会分配一个唯一的标识,该键可以使用种类键名字符串创建。种类是用于组织实体类型的组织桶。例如,我们可能需要为照片、人物和动物设置种类

每个实体都可以有多个开发者定义的属性,这些属性可以具有多种类型的值,包括整数、浮点数、字符串、日期或二进制数据。

    # Create a Cloud Datastore client.
    datastore_client = datastore.Client()

    # Fetch the current date / time.
    current_datetime = datetime.now()

    # The kind for the new entity.
    kind = 'Faces'

    # The name/ID for the new entity.
    name = blob.name

    # Create the Cloud Datastore key for the new entity.
    key = datastore_client.key(kind, name)

    # Construct the new entity using the key. Set dictionary values for entity
    # keys blob_name, storage_public_url, timestamp, and joy.
    entity = datastore.Entity(key)
    entity['blob_name'] = blob.name
    entity['image_public_url'] = blob.public_url
    entity['timestamp'] = current_datetime
    entity['joy'] = face_joy

    # Save the new entity to Datastore.
    datastore_client.put(entity)

Storage 和 Vision 客户端库可以通过编程方式访问,方式与 Datastore 类似。您可以使用 vimemacsnano 自行打开 main.py 文件,以探索所有示例代码。

如需详细了解 Flask,请访问 http://flask.pocoo.org/

如需详细了解客户端库,请访问 https://googlecloudplatform.github.io/google-cloud-python/

homepage.html

Flask Web 框架利用 Jinja2 作为模板引擎。这样一来,我们便可将 main.py 中的变量和表达式传递到 homepage.html 中,这些变量和表达式在网页呈现后会被替换为相应的值。

如需详细了解 Jinja2,请访问 http://jinja.pocoo.org/docs/2.9/templates/

此 Jinja2 HTML 模板显示了一个表单,供用户向数据库提交照片。此外,它还会显示之前提交的每张图片及其文件名、上传日期/时间和 Vision API 检测到的人脸表现出快乐情绪的可能性。

homepage.html

<h1>Google Cloud Platform - Face Detection Sample</h1>

<p>This Python Flask application demonstrates App Engine Flexible, Google Cloud
Storage, Datastore, and the Cloud Vision API.</p>

<br>

<html>
  <body>
    <form action="upload_photo" method="POST" enctype="multipart/form-data">
      Upload File: <input type="file" name="file"><br>
      <input type="submit" name="submit" value="Submit">
    </form>
    
  </body>
</html>

App Engine 柔性环境使用名为 app.yaml 的文件来描述应用的部署配置。如果该文件不存在,App Engine 会尝试推测部署配置。不过,建议您最好提供该文件。

接下来,您将使用自己选择的编辑器(vimnanoemacs)修改 app.yaml。我们将使用 nano 编辑器:

nano app.yaml

app.yaml

runtime: python
env: flex
entrypoint: gunicorn -b :$PORT main:app

runtime_config:
    python_version: 3

env_variables:
    CLOUD_STORAGE_BUCKET: <your-cloud-storage-bucket>

这是部署 Python 3 App Engine 柔性应用所需的基本配置。您可以点击此处详细了解如何配置 App Engine。

打开 app.yaml 后,将 < your-cloud-storage-bucket > 替换为您的 Cloud Storage 存储分区的名称。(如果您忘记了 Cloud Storage 存储分区的名称,请从 Qwiklabs 中复制 GCP 项目 ID,该 ID 与存储分区名称相同)。env_variables 部分用于设置在应用部署后将在 main.py 中使用的环境变量。

现在,您可以使用 (Ctrl + x) 在 nano 中保存并关闭文件,系统会提示:

Screen Shot 2017-02-17 at 4.47.12 PM.png

输入字母 y,然后再次按 ENTER 键,确认以下提示中的文件名:

Screen Shot 2017-02-24 at 4.18.23 PM.png

使用 gcloud 在 App Engine 上部署应用:

gcloud app deploy

部署应用后,您可以在网络浏览器中打开网址 https://< PROJECT_ID >.appspot.com 来访问该应用。

摘要

在此步骤中,您设置了一个 Python Web 应用并将其部署到了 App Engine 柔性环境。

您已了解如何编写和部署您的第一个 App Engine 柔性 Web 应用!

清理

为避免系统因本快速入门中使用的资源向您的 Google Cloud Platform 账号收取费用,请执行以下操作:

  • 访问 Cloud Platform Console
  • 选择要关停的项目,然后点击顶部的“删除”:系统会安排删除该项目。

了解详情

许可

此作品已获得 Creative Commons Attribution 2.0 通用许可授权。