在 App Engine 柔性环境中运行 Django

App Engine 柔性环境上运行的 Django 应用可根据流量动态扩缩。

本教程假定您熟悉 Django 网络开发。如果您不熟悉 Django 开发,最好先编写您的第一个 Django 应用,然后再继续。

虽然本教程专门介绍了 Django,但您可以将此部署过程与其他基于 Django 的框架(如 WagtailDjango CMS)结合使用。

本教程使用 Django 3,它至少需要 Python 3.7。App Engine 柔性环境支持 Python 3.7

目标

在本教程中,您将学习以下操作:

  • 创建并连接 Cloud SQL 数据库。
  • 创建和使用 Secret Manager Secret 值。
  • 将 Django 应用部署到 App Engine 柔性环境。

  • 在 Cloud Storage 上托管静态文件。

费用

在本文档中,您将使用 Google Cloud 的以下收费组件:

您可使用价格计算器根据您的预计使用情况来估算费用。 Google Cloud 新用户可能有资格申请免费试用

开始前须知

  1. 登录您的 Google Cloud 账号。如果您是 Google Cloud 新手,请创建一个账号来评估我们的产品在实际场景中的表现。新客户还可获享 $300 赠金,用于运行、测试和部署工作负载。
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  3. 确保您的 Google Cloud 项目已启用结算功能

  4. Enable the Cloud SQL Admin API, Secret Manager, and Cloud Build APIs.

    Enable the APIs

  5. Install the Google Cloud CLI.
  6. To initialize the gcloud CLI, run the following command:

    gcloud init
  7. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  8. 确保您的 Google Cloud 项目已启用结算功能

  9. Enable the Cloud SQL Admin API, Secret Manager, and Cloud Build APIs.

    Enable the APIs

  10. Install the Google Cloud CLI.
  11. To initialize the gcloud CLI, run the following command:

    gcloud init
  12. 如果您尚未初始化 App Engine 并选择您的首选区域,请执行此操作:

    gcloud app create
    

准备环境

克隆示例应用

Django 示例应用的代码位于 GitHub 上的 GoogleCloudPlatform/python-docs-samples 代码库中。

  1. 您可以下载该示例的 ZIP 文件并将其解压缩,也可以将该代码库克隆到本地机器:

    git clone https://github.com/GoogleCloudPlatform/python-docs-samples.git
    
  2. 转到包含示例代码的目录:

    Linux/macOS

    cd python-docs-samples/appengine/flexible/django_cloudsql
    

    Windows

    cd python-docs-samples\appengine\flexible\django_cloudsql
    

确认 Python 设置

本教程依赖 Python 在机器上运行示例应用。示例代码还需要安装依赖项

如需了解详情,请参阅 Python 开发环境指南

  1. 确认您的 Python 版本至少为 3.7。

     python -V
    

    您应该会看到 Python 3.7.3 或更高。

  2. 创建 Python 虚拟环境并安装依赖项:

    Linux/macOS

    python -m venv venv
    source venv/bin/activate
    pip install --upgrade pip
    pip install -r requirements.txt
    

    Windows

    python -m venv env
    venv\scripts\activate
    pip install --upgrade pip
    pip install -r requirements.txt
    

下载 Cloud SQL Auth 代理以从本地机器连接到 Cloud SQL

部署后,您的应用会使用 App Engine 柔性环境中内置的 Cloud SQL Auth 代理与您的 Cloud SQL 实例进行通信。但是,如需在本地测试应用,您必须在开发环境中安装和使用代理的本地副本。如需了解详情,请参阅 Cloud SQL Auth 代理指南

Cloud SQL Auth 代理使用 Cloud SQL API 与 SQL 实例进行交互。为此,它需要通过 gcloud 进行应用身份验证。

  1. 对 API 进行身份验证并获取凭据:

    gcloud auth application-default login
    
  2. 将 Cloud SQL Auth 代理下载并安装到本地机器。

    Linux 64 位

    1. 下载 Cloud SQL Auth 代理:
      wget https://dl.google.com/cloudsql/cloud_sql_proxy.linux.amd64 -O cloud_sql_proxy
      
    2. 使 Cloud SQL Auth 代理可执行:
      chmod +x cloud_sql_proxy
      

    Linux 32 位

    1. 下载 Cloud SQL Auth 代理:
      wget https://dl.google.com/cloudsql/cloud_sql_proxy.linux.386 -O cloud_sql_proxy
      
    2. 如果找不到 wget 命令,请运行 sudo apt-get install wget 并重复下载命令。
    3. 使 Cloud SQL Auth 代理可执行:
      chmod +x cloud_sql_proxy
      

    macOS 64 位

    1. 下载 Cloud SQL Auth 代理:
      curl -o cloud_sql_proxy https://dl.google.com/cloudsql/cloud_sql_proxy.darwin.amd64
      
    2. 使 Cloud SQL Auth 代理可执行:
      chmod +x cloud_sql_proxy
      

    macOS 32 位

    1. 下载 Cloud SQL Auth 代理:
      curl -o cloud_sql_proxy https://dl.google.com/cloudsql/cloud_sql_proxy.darwin.386
      
    2. 使 Cloud SQL Auth 代理可执行:
      chmod +x cloud_sql_proxy
      

    Mac M1

    1. 下载 Cloud SQL Auth 代理:
        curl -o cloud_sql_proxy https://dl.google.com/cloudsql/cloud_sql_proxy.darwin.arm64
        
    2. 使 Cloud SQL Auth 代理可执行:
        chmod +x cloud_sql_proxy
        

    Windows 64 位

    右键点击 https://dl.google.com/cloudsql/cloud_sql_proxy_x64.exe,然后选择链接另存为以下载 Cloud SQL 身份验证代理。将文件重命名为 cloud_sql_proxy.exe

    Windows 32 位

    右键点击 https://dl.google.com/cloudsql/cloud_sql_proxy_x86.exe,然后选择链接另存为以下载 Cloud SQL 身份验证代理。将文件重命名为 cloud_sql_proxy.exe

    Cloud SQL Auth 代理 Docker 映像

    为方便起见,您可以在 GitHub 的 Cloud SQL Auth 代理代码库中找到多个包含 Cloud SQL Auth 代理的容器映像。您可以使用 Docker 使用以下命令将最新映像拉取到本地机器:
    docker pull gcr.io/cloudsql-docker/gce-proxy:1.19.1
    

    其他操作系统

    对于此处未列出的其他操作系统,您可以从源代码编译 Cloud SQL Auth 代理

    您可以选择将下载内容移到常用位置,例如 PATH 上的某个位置或主目录。如果您选择执行此操作,那么当您在本教程后面部分启动 Cloud SQL Auth 代理时,请务必在使用 cloud_sql_proxy 命令时引用您选择的位置。

创建后备服务

本教程使用多种 Google Cloud 服务来提供支持已部署 Django 项目的数据库、媒体存储空间和密文存储空间。这些服务部署在特定地区中。为了提高服务之间的效率,所有服务都应部署在同一地区。如需详细了解离您最近的地区,请参阅各地区提供的商品

设置 Cloud SQL for PostgreSQL 实例

Django 正式支持多个关系型数据库,但提供了 PostgreSQL 的最大支持。Cloud SQL 支持 PostgreSQL,因此本教程选择使用该类型的数据库。

以下部分介绍如何为应用创建 PostgreSQL 实例、数据库和数据库用户。

  1. 创建 PostgreSQL 实例:

    控制台

    1. 在 Cloud Console 中,转到 Cloud SQL 实例页面。

      转到“Cloud SQL 实例”页面

    2. 点击创建实例

    3. 点击 PostgreSQL

    4. 实例 ID 字段中,输入 INSTANCE_NAME

    5. 为 postgres 用户输入密码。

    6. 其他字段保留默认值。

    7. 点击创建

    创建实例并准备就绪可供使用需要几分钟时间。

    gcloud

    • 创建 PostgreSQL 实例:

      gcloud sql instances create INSTANCE_NAME \
          --project PROJECT_ID \
          --database-version POSTGRES_13 \
          --tier db-f1-micro \
          --region REGION
      

    替换以下内容:

    • INSTANCE_NAME:Cloud SQL 实例名称
    • PROJECT_ID:Google Cloud 项目 ID
    • REGIONGoogle Cloud 地区

    创建实例并准备就绪可供使用需要几分钟时间。

  2. 在已创建的实例中,创建一个数据库:

    控制台

    1. 在实例页面中,转到数据库标签页。
    2. 点击创建数据库
    3. 数据库名称对话框中,输入 DATABASE_NAME
    4. 点击创建

    gcloud

    • 在最近创建的实例中创建数据库:

      gcloud sql databases create DATABASE_NAME \
          --instance INSTANCE_NAME
      

      DATABASE_NAME 替换为实例中数据库的名称。

  3. 创建数据库用户:

    控制台

    1. 在实例页面中,转到用户标签页。
    2. 点击添加用户帐号
    3. 将用户帐号添加到实例对话框的“内置身份验证”下:
    4. 输入用户名 DATABASE_USERNAME
    5. 输入密码 DATABASE_PASSWORD
    6. 点击添加

    gcloud

    • 在最近创建的实例中创建用户:

      gcloud sql users create DATABASE_USERNAME \
          --instance INSTANCE_NAME \
          --password DATABASE_PASSWORD
      

      PASSWORD 替换为安全密码。

设置 Cloud Storage 存储分区

您可以使用 Cloud Storage 将包含 Django 的静态资源以及用户上传的媒体存储在可用性较高的对象存储中。django-storages[google] 软件包会处理 Django 与此存储后端的交互。

控制台

  1. In the Google Cloud console, go to the Cloud Storage Buckets page.

    Go to Buckets page

  2. Click Create bucket.
  3. On the Create a bucket page, enter your bucket information. To go to the next step, click Continue.
    • For Name your bucket, enter a name that meets the bucket naming requirements.
    • For Location, select the following: MEDIA_BUCKET
    • For Choose a default storage class for your data, select the following: Standard.
    • For Choose how to control access to objects, select an Access control option.
    • For Advanced settings (optional), specify an encryption method, a retention policy, or bucket labels.
  4. Click Create.

gcloud

在安装 gcloud CLI 的过程中,安装了 gsutil 命令行工具。

  • 创建 Cloud Storage 存储分区:

    gsutil mb -l REGION gs://PROJECT_ID_MEDIA_BUCKET
    

    MEDIA_BUCKET 替换为媒体存储分区的后缀。结合项目 ID,这将创建一个唯一的存储分区名称。

在 Secret Manager 中存储密文值

在配置后备服务后,Django 需要有关这些服务的信息。本教程使用 Secret Manager 安全地存储这些信息,而不是直接将这些值放入 Django 源代码。

App Engine 柔性环境使用其服务帐号与 Secret 交互。

将 Django 环境文件创建为 Secret Manager Secret

您可以将启动 Django 所需的设置存储在安全的环境变量文件中。示例应用使用 Secret Manager API 检索密钥值,并使用 django-environ 软件包将值加载到 Django 环境中。Secret 配置为可通过 App Engine 柔性环境访问。

  1. 创建一个名为 .env 的文件,该文件定义数据库连接字符串、媒体存储分区名称以及新的 SECRET_KEY 值:

    echo DATABASE_URL=postgres://DATABASE_USERNAME:DATABASE_PASSWORD@//cloudsql/PROJECT_ID:REGION:INSTANCE_NAME/DATABASE_NAME > .env
    echo GS_BUCKET_NAME=PROJECT_ID_MEDIA_BUCKET >> .env
    echo SECRET_KEY=$(cat /dev/urandom | LC_ALL=C tr -dc '[:alpha:]'| fold -w 50 | head -n1) >> .env
    
  2. 将 Secret 存储在 Secret Manager 中:

    控制台

    1. 在 Cloud Console 中,转到 Secret Manager 页面

      转到 Secret Manager 页面

    2. 点击创建 Secret

    3. 名称字段中,输入 django_settings

    4. Secret value 对话框中,粘贴 .env 文件的内容。

    5. 点击创建密钥

    6. 删除本地文件,以防被本地设置覆盖

    gcloud

    1. 使用 .env 文件的值创建新的 Secret django_settings

      gcloud secrets create django_settings --data-file .env
      
    2. 如需确认创建密钥,请检查:

      gcloud secrets describe django_settings
      
      gcloud secrets versions access latest --secret django_settings
      
    3. 删除本地文件以防本地设置覆盖

      rm .env
      
  3. 配置对 Secret 的访问权限:

    控制台

    1. 点击权限标签页。
    2. 点击添加
    3. 新成员字段中,输入 PROJECT_ID@appspot.gserviceaccount.com,然后按 Enter
    4. 角色下拉菜单中,选择 Secret Manager Secret Accessor
    5. 点击保存

    gcloud

    1. 向 App Engine 柔性环境服务帐号授予对 Secret 的访问权限

      gcloud secrets add-iam-policy-binding django_settings \
          --member serviceAccount:PROJECT_ID@appspot.gserviceaccount.com \
          --role roles/secretmanager.secretAccessor
      

在本地计算机上运行应用

配置后备服务后,您就可以在计算机上运行应用了。此设置可用于本地开发、创建超级用户以及应用数据库迁移。

  1. 在单独的终端中,启动 Cloud SQL Auth 代理:

    Linux/macOS

    ./cloud_sql_proxy -instances="PROJECT_ID:REGION:INSTANCE_NAME"=tcp:5432
    

    Windows

    cloud_sql_proxy.exe -instances="PROJECT_ID:REGION:INSTANCE_NAME"=tcp:5432
    

    此步骤会建立从本地计算机到您的 Cloud SQL 实例的连接,以进行本地测试。在您对应用进行本地测试的整个过程中,请确保 Cloud SQL Auth 代理一直运行。在单独的终端中运行此过程可让您在此过程运行时继续工作。

  2. 在新终端中,在本地设置项目 ID(由 Secret Manager API 使用):

    Linux/macOS

      export GOOGLE_CLOUD_PROJECT=PROJECT_ID
    

    Windows

      set GOOGLE_CLOUD_PROJECT=PROJECT_ID
    
  3. 设置一个环境变量,以表明您正在使用 Cloud SQL Auth 代理(在代码中识别此值):

    Linux/macOS

      export USE_CLOUD_SQL_AUTH_PROXY=true
    

    Windows

      set USE_CLOUD_SQL_AUTH_PROXY=true
    
  4. 运行 Django 迁移以设置模型和资源:

    python manage.py makemigrations
    python manage.py makemigrations polls
    python manage.py migrate
    python manage.py collectstatic
    
  5. 启动 Django Web 服务器:

    python manage.py runserver
    
  6. 在浏览器中,转到 http://localhost:8000

    页面上会显示以下文本:“Hello, world. 您可以查看投票索引。在计算机上运行的 Django Web 服务器提供示例应用页面。

  7. Ctrl/Cmd+C 可停止本地网络服务器。

使用 Django 管理控制台

要登录 Django 的管理控制台,您需要创建一个超级用户。由于您已具有与数据库的本地连接,因此可以运行管理命令:

  1. 创建超级用户。系统会提示您输入用户名、电子邮件地址和密码。

    python manage.py createsuperuser
    
  2. 启动本地 Web 服务器:

    python manage.py runserver
    
  3. 在浏览器中,转到 http://localhost:8000/admin

  4. 使用您运行 createsuperuser 时使用的用户名和密码登录登录管理网站。

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

设置所有后备服务并在本地测试应用后,您现在可以将应用部署到 App Engine 柔性环境:

  1. 打开 app.yaml,并使用 Cloud SQL 实例字符串更新 cloud_sql_instances 的值:
    ...
    beta_settings:
        cloud_sql_instances: PROJECT_ID:REGION:INSTANCE_NAME
    
  2. 通过运行以下命令上传该应用,如 app.yaml 所述部署应用,并将新部署的版本设置为默认版本,从而使其处理所有新流量:
    gcloud app deploy
  3. 出现提示时,输入“yes”确认设置。
  4. 等待消息通知您更新已完成。

运行已部署的应用

该应用已部署,现在可以访问了:

  • 打开已部署的网站:

    gcloud app browse
    
  • 或者,显示网址并手动打开:

    gcloud app describe --format "value(defaultHostname)"
    

您的请求由在 App Engine 柔性环境中运行的网络服务器处理。

更新应用

如需更新应用,请更改代码,然后再次运行 gcloud app deploy 命令。

部署会创建应用的新版本并将其提升为默认版本。应用的早期版本仍会保留,与其关联的虚拟机 (VM) 实例也会保留。所有这些应用版本和虚拟机实例都是可计费资源。如需降低费用,请删除应用的非默认版本。

针对生产环境进行配置

您现在已具备有效的 Django 部署,但您可以采取进一步措施来确保应用做好生产准备。

停用调试功能

确认 mysite/settings.py 中的 DEBUG 变量设置为 False。这样可以防止向用户显示详细的错误页面,这可能会泄露配置相关信息

限制数据库用户权限

使用 Cloud SQL 创建的任何用户都具有与 cloudsqlsuperuser 角色关联的权限:CREATEROLECREATEDBLOGIN

为防止 Django 数据库用户拥有这些权限,请在 PostgreSQL 中手动创建该用户。您需要安装 psql 交互式终端,或使用预安装此工具的 Cloud Shell。

控制台

  1. In the Google Cloud console, activate Cloud Shell.

    Activate Cloud Shell

  2. 在 Cloud Shell 中,使用内置终端连接到您的 INSTANCE_NAME 实例:

    gcloud sql connect INSTANCE_NAME --user postgres
    
  3. 输入 postgres 用户密码。

    您目前使用的是psql。您应该会看到 postgres=> 提示符。

  4. 创建用户:

    CREATE USER DATABASE_USERNAME WITH PASSWORD 'DATABASE_PASSWORD';
    

    PASSWORD 替换为随机的唯一密码。

  5. 将新用户授予完整数据库的全部权限:

    GRANT ALL PRIVILEGES ON DATABASE DATABASE_NAME TO DATABASE_USERNAME;
    
  6. 退出psql

    \q
    

gcloud

  1. 启动与 SQL 实例的连接:

    gcloud sql connect INSTANCE_NAME --user postgres
    

    INSTANCE_NAME 替换为已创建的 Cloud SQL 实例。

  2. 输入 postgres 用户密码。

    您目前使用的是psql。您应该会看到 postgres=> 提示符。

  3. 创建用户:

    CREATE USER DATABASE_USERNAME WITH PASSWORD 'DATABASE_PASSWORD';
    
  4. 将新用户授予完整数据库的全部权限:

    GRANT ALL PRIVILEGES ON DATABASE DATABASE_NAME TO DATABASE_USERNAME;
    
  5. 退出psql

    \q
    

了解代码

示例应用

Django 示例应用使用标准 Django 工具创建。以下命令用于创建项目和轮询应用:

django-admin startproject mysite
python manage.py startapp polls

基本视图、模型和路由配置复制自编写您的第一个 Django 应用第 1 部分第 2 部分)。

来自 Secret Manager 的 Secret

settings.py 文件包含代码,该代码使用 Secret Manager Python API 检索最新版本的已命名 Secret 并将其拉取到环境中(使用 django-environ):

env = environ.Env(DEBUG=(bool, False))
env_file = os.path.join(BASE_DIR, ".env")

if os.path.isfile(env_file):
    # Use a local secret file, if provided

    env.read_env(env_file)
# ...
elif os.environ.get("GOOGLE_CLOUD_PROJECT", None):
    # Pull secrets from Secret Manager
    project_id = os.environ.get("GOOGLE_CLOUD_PROJECT")

    client = secretmanager.SecretManagerServiceClient()
    settings_name = os.environ.get("SETTINGS_NAME", "django_settings")
    name = f"projects/{project_id}/secrets/{settings_name}/versions/latest"
    payload = client.access_secret_version(name=name).payload.data.decode("UTF-8")

    env.read_env(io.StringIO(payload))
else:
    raise Exception("No local .env or GOOGLE_CLOUD_PROJECT detected. No secrets found.")

Secret 用于存储多个 Secret 值,以减少需要配置的不同 Secret 的数量。

本地密钥替换值

如果在本地文件系统上发现 .env 文件,则使用该文件,而不是 Secret Manager 中的值。在本地创建 .env 文件有助于进行本地测试(例如,针对 SQLite 数据库进行本地开发,或其他本地设置)。

数据库连接

settings.py 文件包含 SQL 数据库的配置。如果您设置了 USE_CLOUD_SQL_AUTH_PROXY,则 DATABASES 设置会更改为推断 Cloud SQL 身份验证代理的使用情况。

# Use django-environ to parse the connection string
DATABASES = {"default": env.db()}

# If the flag as been set, configure to use proxy
if os.getenv("USE_CLOUD_SQL_AUTH_PROXY", None):
    DATABASES["default"]["HOST"] = "127.0.0.1"
    DATABASES["default"]["PORT"] = 5432

云存储静态

settings.py 文件还使用 django-storages 将 Cloud Storage 媒体存储分区直接集成到项目中:

# Define static storage via django-storages[google]
GS_BUCKET_NAME = env("GS_BUCKET_NAME")
STATIC_URL = "/static/"
DEFAULT_FILE_STORAGE = "storages.backends.gcloud.GoogleCloudStorage"
STATICFILES_STORAGE = "storages.backends.gcloud.GoogleCloudStorage"
GS_DEFAULT_ACL = "publicRead"

App Engine app.yaml

app.yaml 文件包含用于部署到柔性环境的配置信息:

runtime: python
env: flex
entrypoint: gunicorn -b :$PORT mysite.wsgi

beta_settings:
    cloud_sql_instances: PROJECT_ID:REGION:INSTANCE_NAME

runtime_config:
  python_version: 3

清理

为避免因本教程中使用的资源导致您的 Google Cloud 帐号产生费用,请删除包含这些资源的项目,或保留项目并删除个别资源。

删除项目

  1. In the Google Cloud console, go to the Manage resources page.

    Go to Manage resources

  2. In the project list, select the project that you want to delete, and then click Delete.
  3. In the dialog, type the project ID, and then click Shut down to delete the project.

后续步骤