了解如何将示例 Rails 应用部署到 Cloud Run,以及如何将代管式数据库、对象存储、加密 Secret 以及构建流水线与无服务器计算相集成。
部署 Rails 应用涉及将多项服务集成到一起,形成一个整体项目。本教程假定您熟悉 Rails 网页开发。
本教程需要Ruby 3.0 或更高版本(也支持 Ruby 2.7,请参阅“了解代码”部分)和 Rails 6 或更高版本。
目标
- 创建 Cloud SQL 数据库并将其关联到 Active Record
- 创建并使用 Secret Manager 安全地存储和访问 Rails 主密钥
- 通过 Active Storage 托管用户上传的媒体和 Cloud Storage 文件
- 使用 Cloud Build 自动执行构建和数据库迁移
- 将 Rails 应用部署到 Cloud Run
费用
开始前须知
- Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
Enable the Cloud Run, Cloud SQL, Cloud Build, Secret Manager, and Compute Engine APIs.
- Install the Google Cloud CLI.
-
To initialize the gcloud CLI, run the following command:
gcloud init
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
Enable the Cloud Run, Cloud SQL, Cloud Build, Secret Manager, and Compute Engine APIs.
- Install the Google Cloud CLI.
-
To initialize the gcloud CLI, run the following command:
gcloud init
- 确保本教程使用的帐号拥有足够的权限。
准备环境
设置默认项目
运行以下命令,为 gcloud
CLI 设置默认项目配置:
gcloud config set project PROJECT_ID
将 PROJECT_ID
替换为新创建的 Google Cloud 项目 ID
克隆 Rails 应用
Rails 示例应用的代码位于 GitHub 上的 GoogleCloudPlatform/ruby-docs-samples
代码库中。
克隆代码库:
git clone https://github.com/GoogleCloudPlatform/ruby-docs-samples.git
转到包含示例代码的目录并运行以下命令,以确保使用所需的 gem 和依赖项正确设置了应用:
Linux/macOS
cd ruby-docs-samples/run/rails bundle install
Windows
cd ruby-docs-samples\run\rails bundle install
准备支持性服务
本教程使用多种 Google Cloud 服务来提供支持已部署 Rails 项目的数据库、媒体存储空间和密文存储空间。这些服务部署在特定地区中。为了提高服务之间的效率,最好将所有服务部署在同一地区。如需详细了解离您最近的地区,请参阅各地区提供的商品。
设置 Cloud SQL for PostgreSQL 实例
Rails 支持多个关系型数据库,包括 Cloud SQL 提供的多个关系型数据库。本教程使用 PostgreSQL,后者是 Rails 应用常用的开源数据库。
以下部分介绍如何为 Rails 应用创建 PostgreSQL 实例、数据库和数据库用户。
创建 PostgreSQL 实例
控制台
在 Cloud Console 中,转到 Cloud SQL 实例页面。
点击创建实例。
点击选择 PostgreSQL。
在实例 ID 字段中,输入实例的名称 (
INSTANCE_NAME
)。在 Password(密码)字段,输入 postgres 用户的密码。
对于其他字段,请使用默认值。
点击创建实例。
gcloud
创建 PostgreSQL 实例:
gcloud sql instances create INSTANCE_NAME \ --database-version POSTGRES_12 \ --tier db-f1-micro \ --region REGION
替换以下内容:
INSTANCE_NAME
:新的 Cloud SQL 实例名称REGION
:Google Cloud 地区
创建实例并准备就绪可供使用需要几分钟时间。
创建数据库
控制台
在 Cloud Console 中,转到 Cloud SQL 实例页面。
选择 INSTANCE_NAME 实例。
转到数据库标签页。
点击创建数据库。
在数据库名称对话框中,输入
DATABASE_NAME
。点击创建。
gcloud
在最近创建的实例中创建数据库:
gcloud sql databases create DATABASE_NAME \ --instance INSTANCE_NAME
将
DATABASE_NAME
替换为实例中数据库的名称。
创建用户
为数据库用户生成随机密码,并将其写入名为 dbpassword
的文件:
cat /dev/urandom | LC_ALL=C tr -dc '[:alpha:]'| fold -w 50 | head -n1 > dbpassword
控制台
在 Cloud Console 中,转到 Cloud SQL 实例页面。
选择 INSTANCE_NAME 实例。
转到用户标签页。
点击添加用户帐号。
在内置身份验证对话框下:
- 输入用户名
DATABASE_USERNAME
。 - 输入
dbpassword
文件的内容作为密码PASSWORD
。
- 输入用户名
点击添加。
gcloud
在最近创建的实例中创建用户,并将其密码设置为 dbpassword 的内容:
gcloud sql users create DATABASE_USERNAME \ --instance=INSTANCE_NAME --password=$(cat dbpassword)
将
DATABASE_USERNAME
替换为实例中用户的名称。
设置 Cloud Storage 存储分区
您可以使用 Cloud Storage 将 Rails 静态资源和用户上传的媒体托管在高可用性对象存储空间中。
控制台
- In the Google Cloud console, go to the Cloud Storage Buckets page.
- Click Create bucket.
- 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: us-central1
- 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.
- Click Create.
gcloud
在安装 gcloud
CLI 的过程中,安装了 gsutil
命令行工具。
创建 Cloud Storage 存储分区。如需创建唯一的 Cloud Storage 存储分区名称,请使用 PROJECT_ID 和您选择的后缀
MEDIA_BUCKET_SUFFIX
。在 Cloud Storage 中,存储分区名称必须是全局唯一的。gsutil mb -l REGION gs://PROJECT_ID-MEDIA_BUCKET_SUFFIX
创建存储分区后,若要将上传的图片设为公开,请将图片对象的权限更改为可供所有人读取。
控制台
- 在 Google Cloud Console 中,转到 Cloud Storage 浏览器页面。
在存储分区列表中,点击要公开的存储分区的名称。
选择页面顶部附近的权限标签页。
点击添加成员按钮。
随即会显示“添加成员”对话框。
在新成员字段中,输入
allUsers
。在选择角色下拉列表中,选择 Cloud Storage 子菜单,然后点击 Storage Object Viewer 选项。
点击保存。
对象群组被公开共享后,“公共访问权限”列中会针对每个对象显示一个链接图标。您可以点击此图标来获取对象的网址。
如需了解如何在 Ruby 浏览器中获取有关失败操作的详细错误信息,请参阅问题排查。
gcloud
使用
gsutil iam ch
命令公开所有对象。请使用您在创建存储分区时使用的MEDIA_BUCKET_SUFFIX
值。gsutil iam ch allUsers:objectViewer gs://PROJECT_ID-MEDIA_BUCKET_SUFFIX
在 Secret Manager 中存储密文值
配置后备服务后, Rails 需要密码等安全信息来访问这些服务。本教程使用 Rails Credentials 和 Secret Manager 安全地存储这些信息,而不是直接将这些值放入 Rails 源代码中。
创建加密凭据文件并将密钥存储为 Secret Manager Secret
Rails 将密钥存储在名为“config/credentials.yml.enc'”的加密文件中。
可以使用本地 config/master.key
或环境变量 ENV[“RAILS_MASTER_KEY”]
解密文件。在凭据文件中,您可以存储 Cloud SQL 实例数据库密码和其他外部 API 访问密钥。
您可以将此密钥安全地存储在 Secret Manager 中。然后,您可以通过向 Cloud Run 和 Cloud Build 分别授予其各自的服务帐号的访问权限,向其授予该密钥的访问权限。服务帐号由包含项目编号的电子邮件地址标识。
使用以下命令生成
config/credentials.yml.enc
文件:bin/rails credentials:edit
如果未定义主密钥,该命令会创建
config/master.key
,如果文件不存在,该命令会创建config/credentials.yml.enc
文件。这将在您的默认$EDITOR
中打开一个临时文件,其中包含要添加 Secret 的解密内容。将新创建的 PostgreSQL 实例数据库密码从
dbpassword
文件复制并粘贴到凭据文件中:secret_key_base: GENERATED_VALUE gcp: db_password: PASSWORD
Secret 可通过
Rails.application.credentials
访问。例如,Rails.application.credentials.secret_key_base
应返回应用的密钥库,Rails.application.credentials.gcp[:db_passsword]
应返回数据库密码。config/credentials/yml.enc
是以加密方式存储的,但config/master.key
可存储在 Secret Manager 中。控制台
在 Cloud Console 中,转到 Secret Manager 页面。
点击创建 Secret
在名称字段中,输入密钥
RAILS_SECRET_NAME
的名称。在密钥值对话框中,将 mater.key 值粘贴到框中。
点击创建密钥。
在您的密钥的“密钥详情”页面上,记下项目编号:
projects/PROJECTNUM/secrets/RAILS_SECRET_NAME
在权限标签页中,点击添加成员。
在新成员字段中,输入
PROJECTNUM-compute@developer.gserviceaccount.com
,然后按Enter
。在新成员字段中,输入
PROJECTNUM@cloudbuild.gserviceaccount.com
,然后按Enter
。在角色下拉菜单中,选择 Secret Manager Secret Accessor。
点击保存。
gcloud
使用 config/master.key 的值创建新的 Secret:
gcloud secrets create RAILS_SECRET_NAME --data-file config/master.key
将
RAILS_SECRET_NAME
替换为新密钥的名称。如需确认创建密钥,请检查:
gcloud secrets describe RAILS_SECRET_NAME gcloud secrets versions access latest --secret RAILS_SECRET_NAME
获取项目编号的值:
gcloud projects describe PROJECT_ID --format='value(projectNumber)'
向 Cloud Run 服务帐号授予对 Secret 的访问权限:
gcloud secrets add-iam-policy-binding RAILS_SECRET_NAME \ --member serviceAccount:PROJECTNUM-compute@developer.gserviceaccount.com \ --role roles/secretmanager.secretAccessor
将
PROJECTNUM
替换为上述项目编号值。向 Cloud Build 服务帐号授予对 Secret 的访问权限:
gcloud secrets add-iam-policy-binding RAILS_SECRET_NAME \ --member serviceAccount:PROJECTNUM@cloudbuild.gserviceaccount.com \ --role roles/secretmanager.secretAccessor
在输出中,确认
bindings
将两个服务帐号列为成员。
将 Rails 应用连接到生产数据库和存储
本教程使用 PostgreSQL 实例作为生产数据库,使用 Cloud Storage 作为存储后端。为了让 Rails 连接到新创建的数据库和存储分区,您需要在 .env
文件中指定访问这些数据库所需的所有信息。.env
文件包含应用环境变量的配置。该应用将使用 dotenv gem 读取此文件。由于 Secret 存储在 credentials.yml.enc
和 Secret Manager 中,因此 .env
不必加密,因为它不存储任何敏感凭据。
- 如需将 Rails 应用配置为连接到数据库和存储分区,请打开
.env
文件。 将
.env
文件配置修改为以下内容。请使用您在创建存储分区时使用的MEDIA_BUCKET_SUFFIX
值。PRODUCTION_DB_NAME: DATABASE_NAME PRODUCTION_DB_USERNAME: DATABASE_USERNAME CLOUD_SQL_CONNECTION_NAME: PROJECT_ID:REGION:INSTANCE_NAME GOOGLE_PROJECT_ID: PROJECT_ID STORAGE_BUCKET_NAME: PROJECT_ID-MEDIA_BUCKET_SUFFIX
Rails 应用现已设置为在部署到 Cloud Run 时使用 Cloud SQL 和 Cloud Storage。
授予 Cloud Build 对 Cloud SQL 的访问权限
为了让 Cloud Build 应用数据库迁移,您需要授予 Cloud Build 访问 Cloud SQL 的权限。
控制台
在 Cloud Console 中,转到 Identity and Access Management 页面。
如需修改
PROJECTNUM@cloudbuild.gserviceaccount.com
成员的条目,请点击 修改成员。点击添加其他角色
在选择角色对话框中,选择 Cloud SQL 客户。
点击保存。
gcloud
授予 Cloud Build 访问 Cloud SQL 的权限:
gcloud projects add-iam-policy-binding PROJECT_ID \ --member serviceAccount:PROJECTNUM@cloudbuild.gserviceaccount.com \ --role roles/cloudsql.client
将应用部署到 Cloud Run
设置后备服务后,您现在可以将应用部署为 Cloud Run 服务了。
使用提供的
cloudbuild.yaml
,使用 Cloud Build 构建映像、运行数据库迁移并填充静态资源:gcloud builds submit --config cloudbuild.yaml \ --substitutions _SERVICE_NAME=SERVICE_NAME,_INSTANCE_NAME=INSTANCE_NAME,_REGION=REGION,_SECRET_NAME=RAILS_SECRET_NAME
将
SERVICE_NAME
替换为您的服务名称。第一次构建需要几分钟时间才能完成。如果构建超时,请将 --timeout=2000s 插入上述构建命令,以增加超时时长。构建成功后,首次部署 Cloud Run 服务,设置服务区域、基础映像和连接的 Cloud SQL 实例:
gcloud run deploy SERVICE_NAME \ --platform managed \ --region REGION \ --image gcr.io/PROJECT_ID/SERVICE_NAME \ --add-cloudsql-instances PROJECT_ID:REGION:INSTANCE_NAME \ --allow-unauthenticated
您应该会看到显示部署成功的输出,其中包含服务网址:
Service [SERVICE_NAME] revision [SERVICE_NAME-00001-tug] has been deployed and is serving 100 percent of traffic at https://SERVICE_NAME-
HASH
-uc.a.run.app如需查看已部署的服务,请转到服务网址。
请尝试上传新照片。如果照片上传成功,则表示 Rails 应用已成功部署。
更新应用
虽然初始配置和部署步骤较为复杂,但更新流程更为简单:
运行 Cloud Build 构建和迁移脚本:
gcloud builds submit --config cloudbuild.yaml \ --substitutions _SERVICE_NAME=SERVICE_NAME,_INSTANCE_NAME=INSTANCE_NAME,_REGION=REGION,_SECRET_NAME=RAILS_SECRET_NAME
部署服务,仅指定区域和映像:
gcloud run deploy SERVICE_NAME \ --platform managed \ --region REGION \ --image gcr.io/PROJECT_ID/SERVICE_NAME
了解代码
Rails 示例应用使用标准 Rails 命令创建。以下命令将创建 cat_album 应用并使用 scaffold 命令为相册资源生成模型、控制器和视图:
rails new cat_album
rails generate scaffold Photo caption:text
数据库连接
config/database.yml
文件包含在不同环境中(开发、测试、生产)访问数据库所需的配置。例如,生产数据库配置为在 Cloud SQL for PostgreSQL 中运行。数据库名称和用户名通过 .env
文件中的环境变量设置,而数据库密码存储在 config/credentials.yml.enc
文件中,这需要 RAILS_MASTER_KEY
进行解密。
当应用在 Cloud Run(全代管式)上运行时,它使用 Cloud Run 环境提供的套接字连接到 PostgreSQL 实例。 当应用在本地机器上运行时,它会使用 Cloud SQL Auth 代理连接到 PostgreSQL 实例。
云存储用户上传的媒体
Rails 使用 Active Storage 将文件上传到云存储服务商。config/storage.yml
和 config/environments/production.rb
文件将 Cloud Storage 指定为生产环境中的服务提供商。
使用 Cloud Build 实现自动化
cloudbuild.yaml 文件不仅执行典型的映像构建步骤(创建容器映像并将其推送到 Container Registry),还执行 Rails 数据库迁移。这些数据库需要访问数据库,可使用 Cloud SQL 身份验证代理的帮助程序 app-engine-exec-wrapper 执行。
此配置中使用替代变量。直接更改该文件中的值意味着可以在迁移时删除 --substitutions
标志。
在此配置中,仅应用 db/migrate
目录中的现有迁移。如需创建迁移文件,请参阅 Active Record 迁移。
如需构建映像并应用迁移,Cloud Build 配置需要从 Secret Manager 访问 RAILS_MASTER_KEY
Secret。availableSecrets
字段设置用于 Secret 的 Secret 版本和环境变量。主密钥 Secret 作为构建映像步骤中的参数传入,然后在构建映像时设置为 Dockerfile 中的 RAILS_MASTER_KEY
。
要扩展 Cloud Build 配置以将部署包含在一个配置中,而无需运行两个命令,请参阅使用 Cloud Build 从 Git 进行持续部署。如上所述,这需要 IAM 更改。
支持 Ruby 2.7
虽然本教程使用 Ruby 3.0,但它也支持 Ruby 2.7。如需使用 Ruby 2.7,请将 Dockerfile 中的 Ruby 基础映像更改为 2.7
清理
- In the Google Cloud console, go to the Manage resources page.
- In the project list, select the project that you want to delete, and then click Delete.
- In the dialog, type the project ID, and then click Shut down to delete the project.