使用 dotnet publish 容器化 .NET 应用

容器具有许多功能和优势,例如不可变基础结构、提供可移植体系结构和实现可伸缩性。 该映像可用于为本地开发环境、私有云或公有云创建容器。 本教程介绍如何使用 dotnet publish 命令来容器化 .NET 应用程序,而无需使用 Dockerfile。 此外,还介绍了如何配置 容器映像 和执行,以及如何清理资源。

提示

如果有兴趣使用 Dockerfile 容器化 .NET 应用,请参阅 教程:容器化 .NET 应用

先决条件

安装以下必备组件:

  • .NET 8+ SDK
    如果已安装 .NET,请使用 dotnet --info 命令来确定所使用的 SDK。

如果计划在本地运行容器,则需要与开放容器计划(OCI)兼容的容器运行时,例如:

  • Docker Desktop:最常见的容器运行时。
  • Podman:一种无守护进程的开源 Docker 替代方案。

重要

.NET SDK 在不使用 Docker 的情况下创建容器映像。 仅当想要在本地运行映像时,才需要 Docker 或 Podman。 默认情况下,将 .NET 应用作为容器映像发布时,则会将其推送到本地容器运行时。 或者,可以将 映像保存为 tarball,或者直接将其推送到 容器注册表,而无需使用任何容器运行时。

除了这些先决条件之外,建议你熟悉 .NET 中的辅助角色服务,因为示例项目是一个辅助角色。

创建 .NET 应用

需要一个 .NET 应用来容器化,因此首先从模板创建新应用。 打开终端,创建工作文件夹(示例目录),如果尚未这样做,请更改目录,以便你位于其中。 在工作文件夹中运行以下命令,在名为 Worker的子目录中创建新项目:

dotnet new worker -o Worker -n DotNet.ContainerImage

文件夹树类似于以下目录:

📁 sample-directory
    └──📂 Worker
        ├──appsettings.Development.json
        ├──appsettings.json
        ├──DotNet.ContainerImage.csproj
        ├──Program.cs
        ├──Worker.cs
        ├──📂 Properties
        │   └─── launchSettings.json
        └──📂 obj
            ├── DotNet.ContainerImage.csproj.nuget.dgspec.json
            ├── DotNet.ContainerImage.csproj.nuget.g.props
            ├── DotNet.ContainerImage.csproj.nuget.g.targets
            ├── project.assets.json
            └── project.nuget.cache

dotnet new 命令创建一个名为 辅助角色 的新文件夹,并生成一个辅助角色服务,该服务在运行时每隔一秒记录一条消息。 从终端会话,更改目录并导航到 Worker 文件夹。 使用 dotnet run 命令启动应用。

dotnet run
Using launch settings from ./Worker/Properties/launchSettings.json...
Building...
info: DotNet.ContainerImage.Worker[0]
      Worker running at: 01/06/2025 13:37:28 -06:00
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
      Content root path: .\Worker
info: DotNet.ContainerImage.Worker[0]
      Worker running at: 01/06/2025 13:37:29 -06:00
info: DotNet.ContainerImage.Worker[0]
      Worker running at: 01/06/2025 13:37:30 -06:00
info: Microsoft.Hosting.Lifetime[0]
      Application is shutting down...

辅助角色模板无限期循环。 使用 cancel 命令 Ctrl+C 停止它。

设置容器映像名称

将应用发布为容器时,可以使用各种配置选项。 默认情况下,容器映像名称是项目的 AssemblyName。 如果该名称作为容器映像名称无效,可以通过指定 ContainerRepository 来替代它,如以下项目文件中所示:

<Project Sdk="Microsoft.NET.Sdk.Worker">

  <PropertyGroup>
    <TargetFramework>net9.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
    <UserSecretsId>dotnet-DotNet.ContainerImage-2e40c179-a00b-4cc9-9785-54266210b7eb</UserSecretsId>
    <ContainerRepository>dotnet-worker-image</ContainerRepository>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.1" />
  </ItemGroup>
</Project>

要获取进一步参考,请参阅 ContainerRepository

发布 .NET 应用

若要将 .NET 应用发布为容器,请使用以下 dotnet publish 命令:

dotnet publish --os linux --arch x64 /t:PublishContainer

前面的 .NET CLI 命令将应用发布为容器:

  • 以 Linux 为目标,将其作为 OS (--os linux)。
  • 指定 x64 体系结构(--arch x64)。

重要

若要在本地发布容器,必须运行一个符合 OCI 的正在运行的守护程序。 如果在尝试将应用作为容器发布时该应用未运行,您将遇到如下错误:

..\build\Microsoft.NET.Build.Containers.targets(66,9): error MSB4018:
   The "CreateNewImage" task failed unexpectedly. [..\Worker\DotNet.ContainerImage.csproj]

dotnet publish 命令生成类似于示例输出的输出:

Restore complete (0.2s)
  DotNet.ContainerImage succeeded (2.6s) → bin\Release\net9.0\linux-x64\publish\

此命令将您的工作应用编译到 发布 文件夹,并默认将容器镜像推送到本地 Docker 守护程序。 如果使用的是 Podman,则为别名

将 .NET 应用发布到 tarball

tarball(或 tar 文件)是包含其他文件的文件。 它通常以 *.tar.gz复合文件扩展名结尾,以帮助指示它是压缩的存档。 这些文件类型用于分发软件或创建备份。 在这种情况下,创建的 tarball 用于分发容器映像。

若要将 .NET 应用作为容器发布到 tarball,请使用以下命令:

dotnet publish --os linux --arch x64 \
    /t:PublishContainer \
    -p ContainerArchiveOutputPath=./images/container-image.tar.gz

上述命令将应用作为容器发布到 tarball:

  • 以 Linux 为目标,将其作为 OS (--os linux)。
  • 指定 x64 体系结构(--arch x64)。
  • ContainerArchiveOutputPath 属性设置为 ./images/container-image.tar.gz

该命令不需要运行符合 OCI 的守护程序。 有关详细信息,请参阅 ContainerArchiveOutputPath

加载 tarball

导出到 tarball 的一个常见用例是面向以安全为重点的组织。 他们创建容器,将其导出为 tarball 文件,然后对这些 tarball 文件运行安全扫描工具。 此方法简化了合规性,因为它避免了扫描实时系统的复杂性。

tarball 包含整个容器,然后可以使用适当的工具加载:

  • Dockerdocker load -i ./images/container-image.tar.gz
  • Podmanpodman load -i ./images/container-image.tar.gz

将 .NET 应用发布到容器注册表

容器注册表是存储和管理容器映像的服务。 它们用于在多个环境中存储和分发容器映像。 可以使用以下命令将 .NET 应用作为容器发布到容器注册表:

dotnet publish --os linux --arch x64 \
    /t:PublishContainer \
    -p ContainerRegistry=ghcr.io

前面的代码将应用作为容器发布到容器注册表:

  • 将 Linux 设定为目标操作系统(--os linux)。
  • 指定 x64 体系结构(--arch x64)。
  • ContainerRegistry 属性设置为 ghcr.io

有关详细信息,请参阅 ContainerRegistry

清理资源

在本文中,你已将 .NET 辅助角色作为容器映像发布。 如果需要,请删除此资源。 使用 docker images 命令查看已安装映像的列表。

docker images

请考虑以下示例输出:

REPOSITORY             TAG       IMAGE ID       CREATED          SIZE
dotnet-worker-image    1.0.0     25aeb97a2e21   12 seconds ago   191MB

提示

图像文件可能很大。 通常,你将删除在测试和开发应用时创建的临时容器。 如果计划在相应运行时的基础之上生成其他映像,通常会将基础映像与运行时一同安装。

若要删除映像,请复制映像 ID 并运行 docker image rm 命令:

docker image rm 25aeb97a2e21

后续步骤