容器化 .NET 8 Blazor 应用程序并在 GCP Cloud Run 上部署
本文介绍了将容器化的 Web 应用程序(例如 .NET 8 Blazor Web App)部署到 Google Cloud 的过程,并说明了使用 GCP Cloud Run 可以大大简化这一过程。
1. 引言
我最近的项目挑战之一是在 GCP (Google Cloud Platform) 上部署一个容器化的 .NET 8 Web 应用程序。一个显而易见的选项是使用 GKE (Google Kubernetes Engine)。然而,在准备阶段,我发现为 GKE 集群提供 HTTPS 访问需要一些额外的步骤。因此,考虑其他选项是合理的,我决定研究涉及 GCP Cloud Run 的用例,它提供了开箱即用的 HTTPS 访问服务化的 Docker 容器集群。
本文描述了在 Cloud Run 上进行 .NET 8 Blazor Web 应用程序的 Docker 化和部署的用例。该过程涉及以下步骤:
- 在 Windows 10 上生成 .NET 8 Blazor Web App 的脚手架
- 配置端口号
- 在本地文件夹中编译和发布生成的 Web 应用程序(使用 Visual Studio 2022)
- 使用 Docker Desktop 在 Windows 10 上构建 Web 应用程序的 Docker 镜像
- 将镜像导出为 *.tar 格式并导入到 GCP Cloud Shell
- 将 Docker 镜像部署到 GCP Artifact Registry
- 构建一个 Cloud Run 服务,该服务从 GCP Artifact Registry 拉取 Docker 镜像,生成 HTTPS 端点,并运行应用程序
- 测试在 GCP Cloud Run 上运行的已部署的 .NET 8 Blazor Web 应用程序的 HTTPS 访问
本文的核心部分阐述了实现上述部署场景所使用的 bash 和 PowerShell 命令。
2. 源代码
随附的 zip 文件包含用于使用本地 Docker Desktop 构建和运行 Docker 镜像的项目源代码(第 5 节,步骤 4-5)。
3. 使用的技术和工具
本文使用的技术和工具包括:
- .NET 8 SDK,安装在 Windows 10 Pro 上
- Visual Studio 2022 Community Edition,安装在 Windows 10 Pro 上
- Docker Desktop,安装在 Windows 10 Pro 上
- Google Cloud Platform (GCP) 个人账户
- GCP Cloud Console 和 Cloud Shell
- GCP 服务和 API,包括 GCP Artifact Registry 和 GCP Cloud Run
4. GCP Cloud Run 命令介绍
将 Docker 化的 Web 应用程序部署到 GCP Kubernetes Engine (GKE) 集群可能是一个艰巨的过程。特别是,通过 HTTPS 暴露它需要额外的步骤,但 GCP 通过 Cloud Run 提供了一种更简单的方法。在这种方法中,通过在 Cloud Shell 中执行简单的 gcloud 命令,就可以将 Google Artifact Registry (GAR) 中的 Docker 镜像部署为 Cloud Run 服务,从而构建服务并提供应用程序的 HTTPS 端点。以下是该场景的 Cloud Run 命令格式:
gcloud run deploy <service-name> \
--image <region>-docker.pkg.dev/<project-id>/<repository>/<image>:<tag> \
--platform managed \
--port <port-nr>
在上述命令中,参数 <service-name> 是 GCP Cloud Run 服务的名称,例如“my-blazor-app”;<region> 是标准的 GCP 区域名称,例如“europe-west1”;<project-id> 是 GCP 项目 ID;<repository> 表示存储镜像的 Google Artifact Registry 仓库的名称;<image>:<tag> 对表示镜像的名称和标签字符串。参数 <port-nr> 表示 Web 应用程序暴露的端口号。
在 GCP Cloud Shell 中执行此命令时,它会请求一些额外信息,特别是确认 GCP 区域名称,以及确认允许对服务 <service-name> 进行未经身份验证的调用的操作模式。接下来,它将构建服务,此构建将生成一些关于该过程的反馈信息,其中之一是以以下格式提供应用程序的 HTTPS 端点:
https://<service-name>-<additional-id-string>.run.app
5. 实现用例
引言中概述的部署用例通过以下 8 个步骤实现。
步骤 1:创建 .NET 8 Blazor Web 应用程序
我们首先使用 .NET SDK 命令行创建一个 .NET 8 Blazor Web 应用程序。命令“dotnet new blazor …”使用最新的 Blazor 模板来生成默认 Blazor Web 应用程序的脚手架,该应用程序最初是 SSR(服务器端渲染)类型。
dotnet new blazor -n blazorapp -f net8.0 --no-https
步骤 2:设置端口号
下一步是在 Visual Studio 2022 中启动 csproj 文件,并修改 appsettings.json,以便在 Docker 化此应用程序之前和之后始终使用 HTTP 端口 8088。
appsettings.json
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"Kestrel": {
"Endpoints": {
"Http": {
"Url": "http://*:8088"
}
}
}
}
步骤 3:从 Visual Studio 2022 运行 Blazor 应用程序
我们还修改 launchsettings.json 以使用端口 8088,以便在调试模式下运行也使用端点端口号 8088。
步骤 4:发布用于 Linux 容器化的二进制发布
下一步是创建用于 Linux-x64 的二进制发布,以提供与 Docker 容器操作系统(默认为 Linux)的兼容性。Visual Studio 2022 中的发布步骤通过菜单选项“Publish blazorapp”和“Publish to folder”提供此功能。
将 Target Runtime 设置为 linux-x64 后,执行上述步骤会在指定为 Target location ‘bin\release\net8.0\publish\’ 的路径中创建 Blazor 应用程序文件。
应注意的是,此步骤也可以使用 .NET SDK 命令行完成,如下所示:
dotnet publish -c Release -f net8.0 -r linux-x64 -o ./bin/release/net8.0/publish/ --self-contained false
这样,在当前用例中,我们可以自由选择如何发布版本。
应该强调的是,“dotnet publish …”命令在更高级的部署场景中至关重要,因为它为自动化部署提供了可能性。这一点将是我未来出版物的主题。
另一个要点是,如果将“Target runtime”选项设置为“portable”,也会生成一个与 Linux 兼容的镜像。但是,“linux-x64”选项会创建一个为 Linux 优化的容器。因此,这两种选项都可以工作,并且对用例没有影响。
步骤 5:Dockerfile,docker build 和本地测试
为了创建 Docker 镜像,我们首先创建一个 docker 文件,本地 Docker Desktop 将使用该文件来生成镜像。在这里,我们使用 ASPNET 8.0 runtime 作为基础镜像,而不是使用 .NET SDK 作为基础镜像(来自 mcr.microsoft.com/dotnet/sdk:8.0)。在这种情况下,基础镜像会大得多,从而导致我们的构建生成更大的镜像。
Dockerfile
FROM mcr.microsoft.com/dotnet/aspnet:8.0
COPY bin/Release/net8.0/publish/ BlazorAppPublish/
EXPOSE 8088
WORKDIR /BlazorAppPublish
ENTRYPOINT ["dotnet", "blazorapp.dll"]
要执行 Docker build,docker 文件应位于 Visual Studio 2022 项目的根文件夹中(即在 *.csproj 文件旁边)。在 PowerShell 中为 Docker 设置包含 dockerfile 的文件夹的工作目录非常重要。因此,此文件夹的路径是“path/to/blazorapp”(例如 C:\Work\blazorapp)。使用以下命令执行 Docker build 和 Docker run。
docker build -t blazorapp-img -f Dockerfile .
docker run -it -p 8088:8088 --name blazorapp-cnt blazorapp-img
运行创建的镜像 blazorapp-img 可以在 localhost 上测试应用程序,但对于用例实现来说不是必需的。
步骤 6:将镜像导出为 *.tar 并部署到 GCP Artifact Registry
以下 docker 命令将本地 Docker Desktop 中构建的镜像导出到本地 *.tar 文件。
docker save blazorapp-img -o blazorapp-img.tar
接下来,我们使用 Cloud Shell 的上传菜单将 blazorapp-img.tar 文件从本地文件夹上传到 GCP Cloud Shell。
将 *.tar 文件上传到 Cloud Shell 后,可以使用 Cloud Shell 的 Docker 提取镜像。然后,可以对其进行标记并部署到 GCP Artifact Registry (GAR)。这些步骤使用以下命令汇总:
1. 将 *.tar 加载到 Cloud Shell 的 Docker 中
docker load --input blazorapp-img.tar
2. 标记
docker tag blazorapp-img:latest europe-west1-docker.pkg.dev/winged-fact-431520-t4/gar-dockerimg-webapp/blazorapp-img
标记命令使用以下模式:
docker tag <image>:<tag> <region>-docker.pkg.dev/<project-id>/<registry-name>/<image>
3. 部署/推送到 GCP Artifact Registry
docker push europe-west1-docker.pkg.dev/winged-fact-431520-t4/gar-dockerimg-webapp/blazorapp-img
在这种情况下,模式也很容易识别:
docker push <region>-docker.pkg.dev/<project-id>/<registry-name>/<image>
完成此步骤后,镜像将在 GCP Artifact Registry 中可见。
步骤 7:创建 Cloud Run 服务
上传的镜像现在可以由 Cloud Run 服务使用。通过执行“gcloud run deploy <service-name> …”命令来创建这种 GCP 服务,如下所示:
gcloud run deploy blazorappsvc --image europe-west1-docker.pkg.dev/winged-fact-431520-t4/gar-dockerimg-webapp/blazorapp-img:latest --platform managed --port 8088
此命令遵循第 4 节中概述的模式。执行后,系统会要求用户输入以下信息:
- 区域名称
- 允许对 [blazorappsvc] 进行未经身份验证的调用 (y/N)?
提供此输入后,将创建 Cloud Run 服务,并显示以下行:
Deploying container to Cloud Run service [blazorappsvc] in project [winged-fact-431520-t4] region [europe-west1]
OK Deploying new service... Done.
OK Creating Revision...
OK Routing traffic...
OK Setting IAMPolicy... Done.
Service [blazorappsvc] revision [blazorappsvc-00001-ztw] has been deployed and is serving 100 percent of traffic.
Service URL: https://blazorappsvc-ekkselfpua-ew.a.run.app
这样,我们就成功地将 GAR 中的 Blazor 容器部署到了 Cloud Run。Docker 化的 Blazor 应用程序现在作为一个名为 blazorappsvc 的服务运行,并且可以通过一个临时的 Internet 域上的 HTTPS 端点访问:https://blazorappsvc-ekkselfpua-ew.a.run.app。Cloud Run 的状态也可以在 GCP Console 中看到。
步骤 8:测试 HTTPS 访问
Cloud Run 生成的 HTTPS 端点 https://blazorappsvc-ekkselfpua-ew.a.run.app 允许访问已部署的 Blazor Web 应用程序。
6. 值得关注的要点
本文表明,GCP Cloud Run 是容器化 Web 应用程序(如 .NET 8 Blazor Web App)进行云部署的一个有趣的选择,主要是因为它隐藏了 GCP 部署过程中的许多细节,并开箱即用地提供了 HTTPS 访问。
此外,还需要强调的是,GCP Cloud Run 服务基于 Knative 技术构建,这与 GKE 中使用的 Kubernetes 技术不同。另一个好处是,当没有请求时,容器池大小会自动缩减到零,这是一种节省成本的行为。
例如,请参阅 https://cloud.google.com/run/docs/configuring/cpu-allocation。
历史
2024.08.20 - 第一个最终版本。
2024.08.24 - 添加了源代码 zip,修正了少量文本错误。