1. 简介
Cloud Run 是一个代管式计算平台,供您运行可通过 HTTP 请求调用的无状态容器。Cloud Run 采用无服务器设计:您不用管理基础架构,因此可全力专注于最重要的工作,即构建出色的应用。
它还原生与 Google Cloud 生态系统的许多其他部分对接,包括用于托管式数据库的 Cloud SQL、用于统一对象存储的 Cloud Storage 和用于管理 Secret 的 Secret Manager。
Django 是一个高级 Python Web 框架。
在本教程中,您将使用这些组件部署一个小型 Django 项目。
注意:此 Codelab 上次使用 Django 5.0 进行验证。除非未来更新有任何重大更改,否则此 Codelab 应该会继续正常运行。查看未来的 Django 版本说明。
学习内容
- 如何使用 Cloud Shell
- 如何创建 Cloud SQL 数据库
- 如何创建 Cloud Storage 存储分区
- 如何创建 Secret Manager Secret
- 如何使用不同 Google Cloud 服务中的 Secret
- 如何将 Google Cloud 组件连接到 Cloud Run 服务
- 如何使用 Container Registry 存储构建的容器
- 如何部署到 Cloud Run
- 如何在 Cloud Build 中运行数据库架构迁移
2. 设置和要求
自定进度的环境设置
- 登录 Google Cloud 控制台,然后创建一个新项目或重复使用现有项目。如果您还没有 Gmail 或 Google Workspace 账号,则必须创建一个。
- 项目名称是此项目参与者的显示名称。它是 Google API 尚未使用的字符串。您可以随时对其进行更新。
- 项目 ID 在所有 Google Cloud 项目中是唯一的,并且是不可变的(一经设置便无法更改)。Cloud 控制台会自动生成一个唯一字符串;通常情况下,您无需关注该字符串。在大多数 Codelab 中,您都需要引用项目 ID(通常用
PROJECT_ID
标识)。如果您不喜欢生成的 ID,可以再随机生成一个 ID。或者,您也可以尝试自己的项目 ID,看看是否可用。完成此步骤后便无法更改该 ID,并且此 ID 在项目期间会一直保留。 - 此外,还有第三个值,即部分 API 使用的项目编号,供您参考。如需详细了解所有这三个值,请参阅文档。
- 接下来,您需要在 Cloud 控制台中启用结算功能,以便使用 Cloud 资源/API。运行此 Codelab 应该不会产生太多的费用(如果有的话)。若要关闭资源以避免产生超出本教程范围的结算费用,您可以删除自己创建的资源或删除项目。Google Cloud 新用户符合参与 300 美元免费试用计划的条件。
Google Cloud Shell
虽然 Google Cloud 可以通过笔记本电脑远程操作,但在此 Codelab 中,我们将使用 Google Cloud Shell,这是一个在云端运行的命令行环境。
激活 Cloud Shell
- 在 Cloud Console 中,点击激活 Cloud Shell。
如果这是您首次启动 Cloud Shell,系统会显示一个中间屏幕,介绍 Cloud Shell 是什么。如果系统显示中间屏幕,请点击继续。
预配和连接到 Cloud Shell 只需花几分钟时间。
此虚拟机已加载所需的所有开发工具。它提供了一个持久的 5 GB 主目录,并在 Google Cloud 中运行,大大增强了网络性能和身份验证功能。您在此 Codelab 中的大部分(甚至全部)工作都可以使用浏览器完成。
在连接到 Cloud Shell 后,您应该会看到自己已通过身份验证,并且相关项目已设置为您的项目 ID。
- 在 Cloud Shell 中运行以下命令以确认您已通过身份验证:
gcloud auth list
命令输出
Credentialed Accounts ACTIVE ACCOUNT * <my_account>@<my_domain.com> To set the active account, run: $ gcloud config set account `ACCOUNT`
- 在 Cloud Shell 中运行以下命令,以确认 gcloud 命令了解您的项目:
gcloud config list project
命令输出
[core] project = <PROJECT_ID>
如果不是上述结果,您可以使用以下命令进行设置:
gcloud config set project <PROJECT_ID>
命令输出
Updated property [core/project].
3. 启用 Cloud API
在 Cloud Shell 中,为要使用的组件启用 Cloud API:
gcloud services enable \ run.googleapis.com \ sql-component.googleapis.com \ sqladmin.googleapis.com \ compute.googleapis.com \ cloudbuild.googleapis.com \ secretmanager.googleapis.com \ artifactregistry.googleapis.com
由于这是您首次通过 gcloud 调用 API,因此系统会要求您授权使用您的凭据发出此请求。这将在每个 Cloud Shell 会话中执行一次。
此操作可能需要一点时间才能完成。
完成后,您应该会看到类似如下的成功消息:
Operation "operations/acf.cc11852d-40af-47ad-9d59-477a12847c9e" finished successfully.
4. 创建模板项目
您将使用默认 Django 项目模板作为示例 Django 项目。
如需创建此模板项目,请使用 Cloud Shell 创建一个名为 django-cloudrun
的新目录并前往此目录:
mkdir ~/django-cloudrun cd ~/django-cloudrun
然后,将 Django 安装到临时虚拟环境中:
virtualenv venv source venv/bin/activate pip install Django
将已安装软件包的列表保存到 requirements.txt
pip freeze > requirements.txt
此列表应包含 Django 及其依赖项:sqlparse
和 asgiref
。
然后,创建一个新的模板项目:
django-admin startproject myproject .
您将获得一个名为 manage.py
的新文件以及一个名为 myproject
的新文件夹,其中包含许多文件,其中包括一个 settings.py
。
确认顶级文件夹的内容符合预期:
ls -F
manage.py myproject/ requirements.txt venv/
确认 myproject
文件夹的内容符合预期:
ls -F myproject/
__init__.py asgi.py settings.py urls.py wsgi.py
您现在可以退出并移除临时虚拟环境:
deactivate rm -rf venv
从此处,您将在 容器中调用 Django。
5. 创建支持性服务
现在,您将创建支持性服务:专用服务账号、Artifact Registry、Cloud SQL 数据库、Cloud Storage 存储分区和多个 Secret Manager 值。
保护部署中使用的密码值对于任何项目的安全性都非常重要,可确保没有人意外地将密码放在不应输入的位置(例如,直接在设置文件中,或直接在终端中输入密码,以便从历史记录中检索到密码)。
首先,设置两个基本环境变量,一个用于项目 ID:
PROJECT_ID=$(gcloud config get-value core/project)
另一个用于区域:
REGION=us-central1
创建服务账号
如需限制服务对 Google Cloud 其他部分的访问权限,请创建一个专用服务账号:
gcloud iam service-accounts create cloudrun-serviceaccount
在本 Codelab 的后续部分中,您将通过电子邮件地址引用此账号。在环境变量中设置该值:
SERVICE_ACCOUNT=$(gcloud iam service-accounts list \ --filter cloudrun-serviceaccount --format "value(email)")
创建 Artifact Registry
如需存储构建的容器映像,请在所选区域中创建一个 Container Registry:
gcloud artifacts repositories create containers --repository-format docker --location $REGION
在此 Codelab 的后续部分中,您将通过名称引用此注册表:
ARTIFACT_REGISTRY=${REGION}-docker.pkg.dev/${PROJECT_ID}/containers
创建数据库
创建 Cloud SQL 实例:
gcloud sql instances create myinstance --project $PROJECT_ID \ --database-version POSTGRES_14 --tier db-f1-micro --region $REGION
此操作可能需要几分钟才能完成。
在该实例中,创建一个数据库:
gcloud sql databases create mydatabase --instance myinstance
在同一实例中,创建一个用户:
DJPASS="$(cat /dev/urandom | LC_ALL=C tr -dc 'a-zA-Z0-9' | fold -w 30 | head -n 1)" gcloud sql users create djuser --instance myinstance --password $DJPASS
向服务账号授予连接到实例的权限:
gcloud projects add-iam-policy-binding $PROJECT_ID \ --member serviceAccount:${SERVICE_ACCOUNT} \ --role roles/cloudsql.client
创建存储桶
创建一个 Cloud Storage 存储桶(请注意,名称必须是全局唯一的):
GS_BUCKET_NAME=${PROJECT_ID}-media gcloud storage buckets create gs://${GS_BUCKET_NAME} --location ${REGION}
向服务账号授予管理存储桶的权限:
gcloud storage buckets add-iam-policy-binding gs://${GS_BUCKET_NAME} \ --member serviceAccount:${SERVICE_ACCOUNT} \ --role roles/storage.admin
将配置存储为 Secret
设置好后备服务后,您现在需要将这些值存储在使用 Secret Manager 保护的文件中。
借助 Secret Manager,您可以将 Secret 作为二进制 blob 或文本字符串进行存储、管理和访问。它非常适合存储配置信息,例如数据库密码、API 密钥或应用在运行时所需的 TLS 证书。
首先,创建一个包含以下值的文件:数据库连接字符串、媒体存储分区、Django 的密钥(用于会话和令牌的加密签名)并启用调试:
echo DATABASE_URL=\"postgres://djuser:${DJPASS}@//cloudsql/${PROJECT_ID}:${REGION}:myinstance/mydatabase\" > .env echo GS_BUCKET_NAME=\"${GS_BUCKET_NAME}\" >> .env echo SECRET_KEY=\"$(cat /dev/urandom | LC_ALL=C tr -dc 'a-zA-Z0-9' | fold -w 50 | head -n 1)\" >> .env echo DEBUG=True >> .env
然后,创建一个名为 application_settings
的 Secret,并将该文件用作 Secret:
gcloud secrets create application_settings --data-file .env
允许服务账号访问此 Secret:
gcloud secrets add-iam-policy-binding application_settings \ --member serviceAccount:${SERVICE_ACCOUNT} --role roles/secretmanager.secretAccessor
列出 Secret 以确认已创建 Secret:
gcloud secrets versions list application_settings
确认已创建 Secret 后,请移除本地文件:
rm .env
6. 配置应用
鉴于您刚刚创建的后备服务,您需要对模板项目进行一些更改以使其适用。
这将包括引入 django-environ
以将环境变量用作配置设置,您将使用您定义为 Secret 的值作为种子。若要实现此目标,您需要扩展模板设置。您还需要添加其他 Python 依赖项。
配置设置
移动 settings.py
文件,并将其重命名为 basesettings.py:
mv myproject/settings.py myproject/basesettings.py
使用 Cloud Shell Web 编辑器,使用以下代码创建新的 settings.py
文件:
touch myproject/settings.py cloudshell edit myproject/settings.py
myproject/settings.py
import io
import os
from urllib.parse import urlparse
import environ
# Import the original settings from each template
from .basesettings import *
# Load the settings from the environment variable
env = environ.Env()
env.read_env(io.StringIO(os.environ.get("APPLICATION_SETTINGS", None)))
# Setting this value from django-environ
SECRET_KEY = env("SECRET_KEY")
# Ensure myproject is added to the installed applications
if "myproject" not in INSTALLED_APPS:
INSTALLED_APPS.append("myproject")
# If defined, add service URLs to Django security settings
CLOUDRUN_SERVICE_URLS = env("CLOUDRUN_SERVICE_URLS", default=None)
if CLOUDRUN_SERVICE_URLS:
CSRF_TRUSTED_ORIGINS = env("CLOUDRUN_SERVICE_URLS").split(",")
# Remove the scheme from URLs for ALLOWED_HOSTS
ALLOWED_HOSTS = [urlparse(url).netloc for url in CSRF_TRUSTED_ORIGINS]
else:
ALLOWED_HOSTS = ["*"]
# Default false. True allows default landing pages to be visible
DEBUG = env("DEBUG", default=False)
# Set this value from django-environ
DATABASES = {"default": env.db()}
# Change database settings if using the Cloud SQL Auth Proxy
if os.getenv("USE_CLOUD_SQL_AUTH_PROXY", None):
DATABASES["default"]["HOST"] = "127.0.0.1"
DATABASES["default"]["PORT"] = 5432
# Define static storage via django-storages[google]
GS_BUCKET_NAME = env("GS_BUCKET_NAME")
STATICFILES_DIRS = []
GS_DEFAULT_ACL = "publicRead"
STORAGES = {
"default": {
"BACKEND": "storages.backends.gcloud.GoogleCloudStorage",
},
"staticfiles": {
"BACKEND": "storages.backends.gcloud.GoogleCloudStorage",
},
}
请花些时间阅读针对每项配置添加的注释。
请注意,您可能会在此文件中看到执行 lint 请求错误。这是正常现象。Cloud Shell 不了解此项目的要求上下文,因此可能会报告无效导入和未使用的导入。
Python 依赖项
找到 requirements.txt
文件,并附加以下软件包:
cloudshell edit requirements.txt
requirements.txt(附加)
gunicorn psycopg2-binary django-storages[google] django-environ
定义应用映像
Cloud Run 会运行任何符合 Cloud Run 容器合同的容器。本教程选择省略 Dockerfile
,改用 Cloud Native Buildpacks。Buildpack 有助于为常用语言(包括 Python)构建容器。
本教程选择自定义用于启动 Web 应用的 Procfile
。
如需将模板项目容器化,请先在项目的顶层(与 manage.py
位于同一目录中)创建一个名为 Procfile
的新文件,并复制以下内容:
touch Procfile cloudshell edit Procfile
Procfile
web: gunicorn --bind 0.0.0.0:$PORT --workers 1 --threads 8 --timeout 0 myproject.wsgi:application
7. 配置、构建和运行迁移步骤
如需在 Cloud SQL 数据库中创建数据库架构并使用静态资源填充 Cloud Storage 存储桶,您需要运行 migrate
和 collectstatic
。
这些基本 Django 迁移命令需要在具有对数据库访问权限的构建容器映像上下文中运行。
您还需要运行 createsuperuser
来创建一个管理员账号以登录 Django 管理员。
为此,您将使用 Cloud Run 作业来执行这些任务。借助 Cloud Run 作业,您可以运行具有明确结束时间的进程,非常适合执行管理任务。
定义您的 Django 超级用户密码
如需创建超级用户,您将使用非交互式版本的 createsuperuser
命令。此命令需要使用一个特殊命名的环境变量来代替输入密码的提示。
使用随机生成的密码创建新的 Secret:
echo -n $(cat /dev/urandom | LC_ALL=C tr -dc 'a-zA-Z0-9' | fold -w 30 | head -n 1) | gcloud secrets create django_superuser_password --data-file=-
允许您的服务账号访问此 Secret:
gcloud secrets add-iam-policy-binding django_superuser_password \ --member serviceAccount:${SERVICE_ACCOUNT} \ --role roles/secretmanager.secretAccessor
更新您的个人资料
为帮助明确您的 Cloud Run 作业,请在 Procfile 中创建快捷方式,将以下入口点附加到 Procfile
:
migrate: python manage.py migrate && python manage.py collectstatic --noinput --clear createuser: python manage.py createsuperuser --username admin --email noop@example.com --noinput
您现在应该有三个条目:默认的 web
入口点、用于应用数据库迁移的 migrate
入口点,以及用于运行 createsuperuser
命令的 createuser
入口点。
构建应用映像
更新 Procfile 后,构建映像:
gcloud builds submit --pack image=${ARTIFACT_REGISTRY}/myimage
创建 Cloud Run 作业
现在,该映像已存在,您可以使用它创建 Cloud Run 作业。
这些作业使用之前构建的映像,但使用不同的 command
值。它们对应 Procfile
中的值。
为迁移创建作业:
gcloud run jobs create migrate \ --region $REGION \ --image ${ARTIFACT_REGISTRY}/myimage \ --set-cloudsql-instances ${PROJECT_ID}:${REGION}:myinstance \ --set-secrets APPLICATION_SETTINGS=application_settings:latest \ --service-account $SERVICE_ACCOUNT \ --command migrate
为创建用户创建作业:
gcloud run jobs create createuser \ --region $REGION \ --image ${ARTIFACT_REGISTRY}/myimage \ --set-cloudsql-instances ${PROJECT_ID}:${REGION}:myinstance \ --set-secrets APPLICATION_SETTINGS=application_settings:latest \ --set-secrets DJANGO_SUPERUSER_PASSWORD=django_superuser_password:latest \ --service-account $SERVICE_ACCOUNT \ --command createuser
执行 Cloud Run 作业
完成作业配置后,运行迁移:
gcloud run jobs execute migrate --region $REGION --wait
确保此命令输出显示执行“已成功完成”。
您稍后在更新应用时将运行此命令。
设置好数据库后,使用作业创建用户:
gcloud run jobs execute createuser --region $REGION --wait
确保此命令输出显示执行“已成功完成”。
您无需再次运行此命令。
8. 部署到 Cloud Run
创建并填充支持性服务后,您现在可以创建 Cloud Run 服务来访问这些服务。
使用以下命令,使用您之前构建的映像将服务部署到 Cloud Run:
gcloud run deploy django-cloudrun \ --region $REGION \ --image ${ARTIFACT_REGISTRY}/myimage \ --set-cloudsql-instances ${PROJECT_ID}:${REGION}:myinstance \ --set-secrets APPLICATION_SETTINGS=application_settings:latest \ --service-account $SERVICE_ACCOUNT \ --allow-unauthenticated
成功部署后,命令行中便会显示该服务的网址:
Service [django-cloudrun] revision [django-cloudrun-00001-...] has been deployed and is serving 100 percent of traffic. Service URL: https://django-cloudrun-...run.app
现在,您可以在网络浏览器中打开以下网址,访问您部署的容器:
9. 访问 Django 管理
Django 的主要功能之一是其交互式管理。
更新 CSRF 设置
Django 包含防范跨站请求伪造 (CSRF) 的保护措施。每当您在 Django 网站上提交表单(包括登录 Django 管理界面)时,系统都会检查“受信任的来源”设置。如果它与请求的来源不匹配,Django 将返回错误。
在 mysite/settings.py
文件中,如果定义了 CLOUDRUN_SERVICE_URL
环境变量,则会在 CSRF_TRUSTED_ORIGINS
和 ALLOWED_HOSTS
设置中使用该变量。虽然定义 ALLOWED_HOSTS
并非强制性要求,但最好添加此定义,因为 CSRF_TRUSTED_ORIGINS
已包含它。
由于您需要服务网址,因此在首次部署之前无法添加此配置。
您必须更新服务才能添加此环境变量。它可以添加到 application_settings
Secret 中,也可以作为环境变量直接添加。
检索您的服务网址:
CLOUDRUN_SERVICE_URLS=$(gcloud run services describe django-cloudrun \ --region $REGION \ --format "value(metadata.annotations[\"run.googleapis.com/urls\"])" | tr -d '"[]') echo $CLOUDRUN_SERVICE_URLS
在 Cloud Run 服务中将此值设置为环境变量:
gcloud run services update django-cloudrun \ --region $REGION \ --update-env-vars "^##^CLOUDRUN_SERVICE_URLS=$CLOUDRUN_SERVICE_URLS"
登录 Django 管理控制台
要访问 Django 管理界面,请将 /admin
附加到您的服务网址。
现在,使用用户名“admin”登录并使用以下命令检索密码:
gcloud secrets versions access latest --secret django_superuser_password && echo ""
10. 开发应用
在开发应用时,您需要在本地对其进行测试。为此,您需要连接到 Cloud SQL(“生产”)数据库或本地(“测试”)数据库。
连接到生产数据库
您可以使用 Cloud SQL Auth 代理连接到 Cloud SQL 实例。此应用将创建从本地机器到数据库的连接。
安装 Cloud SQL Auth 代理后,请按以下步骤操作:
# Create a virtualenv virtualenv venv source venv/bin/activate pip install -r requirements.txt # Copy the application settings to your local machine gcloud secrets versions access latest --secret application_settings > temp_settings # Run the Cloud SQL Auth Proxy ./cloud-sql-proxy --instances=${PROJECT_ID}:${REGION}:myinstance=tcp:5432 # In a new tab, start the local web server using these new settings USE_CLOUD_SQL_AUTH_PROXY=true APPLICATION_SETTINGS=$(cat temp_settings) python manage.py runserver
请务必在完成工作后移除 temp_settings
文件。
连接到本地 SQLite 数据库
或者,您也可以在开发应用时使用本地数据库。Django 同时支持 PostgreSQL 和 SQLite 数据库,PostgreSQL 具有 SQLite 不具备的一些功能,但在许多情况下,两者的功能是相同的。
如需设置 SQLite,您必须更新应用设置,使其指向本地数据库,然后必须应用架构迁移。
如需设置此方法,请执行以下操作:
# Create a virtualenv virtualenv venv source venv/bin/activate pip install -r requirements.txt # Copy the application settings to your local machine gcloud secrets versions access latest --secret application_settings > temp_settings # Edit the DATABASE_URL setting to use a local sqlite file. For example: DATABASE_URL=sqlite:////tmp/my-tmp-sqlite.db # Set the updated settings as an environment variable APPLICATION_SETTINGS=$(cat temp_settings) # Apply migrations to the local database python manage.py migrate # Start the local web server python manage.py runserver
请务必在完成工作后移除 temp_settings
文件。
创建迁移
更改数据库模型时,您可能需要通过运行 python manage.py makemigrations
来生成 Django 的迁移文件。
设置生产或测试数据库连接后,您可以运行此命令。或者,您可以通过指定空设置,在不使用数据库的情况下生成迁移文件:
SECRET_KEY="" DATABASE_URL="" GS_BUCKET_NAME="" python manage.py makemigrations
应用更新
要将更改应用到您的应用,您需要执行以下操作:
- 将更改构建为新映像,
- 执行任何数据库迁移或静态迁移
- 更新 Cloud Run 服务以使用新映像。
如需构建映像,请执行以下操作:
gcloud builds submit --pack image=${ARTIFACT_REGISTRY}/myimage
如果您要应用任何迁移,请运行 Cloud Run 作业:
gcloud run jobs execute migrate --region $REGION --wait
如需使用新映像更新您的服务,请执行以下操作:
gcloud run services update django-cloudrun \ --region $REGION \ --image ${ARTIFACT_REGISTRY}/myimage
11. 恭喜!
您刚刚将一个复杂的项目部署到了 Cloud Run!
- Cloud Run 可以对您的容器映像进行自动横向扩容以处理收到的请求,并在需求减少时缩容。您只需为在处理请求期间消耗的 CPU、内存和网络付费。
- Cloud SQL 可让您预配一个为您自动维护的代管式 PostgreSQL 实例,该实例以原生方式集成到许多 Google Cloud 系统中。
- Cloud Storage 可让您在 Django 中无缝访问云端存储空间。
- 借助 Secret Manager,您可以存储 Secret,并让 Google Cloud 的某些部分(而非其他部分)可以访问 Secret。
清理
为避免因本教程中使用的资源导致您的 Google Cloud Platform 账号产生费用,请执行以下操作:
- 在 Cloud Console 中,转到管理资源页面。
- 在项目列表中,选择您的项目,然后点击删除。
- 在对话框中输入项目 ID,然后点击关停以删除项目。
了解详情
- Django on Cloud Run:https://cloud.google.com/python/django/run
- Hello Cloud Run with Python:https://codelabs.developers.google.com/codelabs/cloud-run-hello-python3
- Google Cloud 上的 Python:https://cloud.google.com/python
- Google Cloud Python 客户端:https://github.com/googleapis/google-cloud-python