.NET应用程序发布概述

本文介绍了发布.NET应用程序的不同方法。 它涵盖发布模式、如何生成可执行文件和跨平台二进制文件,以及每个方法对部署和运行时环境的影响。 可以使用 .NET CLI 或 Visual Studio 发布.NET应用程序。

有关发布的简短教程,请参阅 Tutorial:发布.NET控制台应用程序。

有关发布的简短教程,请参阅 Tutorial:发布.NET控制台应用程序。

什么是发布

发布.NET应用意味着编译源代码以创建可执行文件或二进制文件及其依赖项和相关文件以供分发。 发布后,可将应用部署到服务器、分发平台、容器或云环境。 发布过程为应用在开发环境之外的部署和使用做好准备。

发布模式

发布应用有两种主要方法。 影响此决策的一些因素包括部署环境是否安装了适当的.NET运行时,以及是否需要将运行时与应用捆绑的特定编译功能。 这两种发布模式包括:

  • 发布独立应用
    此模式生成一个发布文件夹,其中包含用于启动应用的特定于平台的可执行文件、包含应用代码的已编译二进制文件、任何应用依赖项以及运行应用所需的.NET运行时。 运行应用的环境不需要预安装.NET运行时。

  • 发布依赖于框架的应用
    此模式生成一个发布文件夹,其中包含用于启动应用的可选特定于平台的可执行文件、包含应用代码的已编译二进制文件以及任何应用依赖项。 运行应用的环境必须安装应用可以使用的 .NET 运行时版本。

重要

使用运行时标识符(RID)指定目标平台。 有关 RID 的详细信息,请参阅 .NET RID 目录。

出版基础知识

发布 <TargetFramework> 应用时,项目文件的设置指定默认目标框架。 可以将目标框架更改为任意有效目标框架名字对象 (TFM)。 例如,如果项目使用 <TargetFramework>net9.0</TargetFramework>,则会创建面向 .NET 9 的二进制文件。

如果要以多个框架为目标,可以将 <TargetFrameworks> 设置为多个 TFM 值,用分号分隔。 生成应用时,将针对项目定义的每个目标框架生成应用。 但是,发布应用时,必须指定目标框架:

默认生成配置模式为 Release,除非使用 -c 参数进行更改。

dotnet publish -c Release -f net9.0

命令的默认输出目录 dotnet publish 为 ./bin/<BUILD-CONFIGURATION>/<TFM>/publish/。 例如, dotnet publish -c Release -f net9.0 发布到 ./bin/Release/net9.0/publish/. 但是,可以选择为所有生成输出选择简化的输出路径和文件夹结构。 有关详细信息,请参阅 Artifacts 输出布局。

重要

通过传递 --no-build 参数在发布过程中跳过生成步骤时,请使用生成应用时所用的相同选项,包括目标框架和生成模式。 例如,不要构建为依赖于框架的应用,然后发布为自包含应用。

在Visual Studio中,为每个目标框架创建单独的发布配置文件。

可移植二进制文件

发布.NET应用时,可以面向特定平台或创建可移植二进制文件。 默认情况下,即使创建可移植二进制文件,.NET也会将特定于平台的可执行文件(“apphost”)与可移植 DLL 一起发布,除非显式禁用此行为。

由于UseAppHost属性默认为true,因此创建了特定于平台的可执行文件。 若要仅发布可移植 DLL 而不包括平台特定的可执行文件,请在命令行中设置 UseAppHost 为 false(-p:UseAppHost=false),或将其作为 项目属性。

面向特定平台的好处是,它可以处理应用可能需要的 本机依赖项 ,确保与目标平台的特定要求兼容。

本机依赖项

如果应用具有本机依赖项,则发布为可移植二进制文件时,它可能不会在不同的作系统上运行。 例如,依赖于 Windows API 的应用不会在 macOS 或 Linux 上本机运行。 你需要提供特定于平台的代码并为每个平台编译可执行文件。

此外,如果引用的库提供特定于平台的依赖项,则应用可能不会在每个平台上运行。 但是,当你发布和面向特定平台时,NuGet 包的特定于平台的依赖项将复制到发布文件夹。

若要确保应用使用其本机依赖项发布,请针对特定平台发布:

dotnet publish -c Release -r <RID>
  • -c Release

    此开关将生成配置设置为 Release,该版本已针对生产部署进行优化。

  • -r <RID>

    此开关使用运行时标识符(RID)来指定目标平台,并确保包含本机依赖项(如果需要)。 有关运行时标识符的列表,请参阅 运行时标识符(RID)目录。

  1. 右键单击 解决方案资源管理器 中的项目,然后选择 Publish。
  2. 如果这是首次发布,请选择 “文件夹 ”作为发布目标,然后选择“ 下一步”。
  3. 选择文件夹位置或接受默认值,然后选择“ 完成”。
  4. 在发布配置文件中,选择“ 显示所有设置”。
  5. 将 Target Runtime设置为所需的平台(例如,64 位Windows的 win-x64)。
  6. 选择“ 保存 ”,然后选择 “发布”。

有关运行时标识符的列表,请参阅 运行时标识符(RID)目录。

快速参考

下表提供了有关如何使用 dotnet CLI 发布应用的快速示例:

发布模式 命令
依赖于框架的部署 dotnet publish -c Release [-r <RID>]
依赖于框架的部署 (DLL) dotnet publish -c Release -p:UseAppHost=false
独立部署 dotnet publish -c Release [-r <RID>] --self-contained true
单文件部署 dotnet publish -c Release [-r <RID>] -p:PublishSingleFile=true
本机 AOT 部署 dotnet publish -c Release [-r <RID>] -p:PublishAot=true
ReadyToRun 部署 dotnet publish -c Release [-r <RID>] -p:PublishReadyToRun=true
容器部署 dotnet publish -c Release [-r <RID>] -t:PublishContainer

作为依赖于框架的应用发布

从 CLI 或Visual Studio发布时,依赖于框架的部署是默认模式。 在此模式下,将创建一个特定于平台的可执行文件,可用于启动应用。 特定于平台的可执行文件的名称类似于 Windows 上的 myapp.exe,或者在其他平台上仅myapp。

你的应用配置为以特定版本的.NET为目标。 目标 .NET 运行时必须在运行应用的环境上。 例如,如果应用面向 .NET 9,则应用运行的任何环境都必须安装 .NET 9 运行时。

发布依赖于框架的应用部署会创建一个应用,该应用会自动更新到运行该应用的环境中可用的最新.NET安全修补程序。 有关编译时的版本绑定的详细信息,请参阅选择要使用的.NET版本。

优点

  • 小型部署:仅分发应用及其依赖项。 运行应用的环境必须已安装.NET运行时。
  • Cross-platform:应用和任何基于.NET的库在其他作系统上运行。
  • 使用最新的修补运行时:应用使用环境中安装的最新运行时。

缺点

  • 预安装运行时:仅当环境中已安装其目标.NET版本时,应用才能运行。
  • .NET可能会更改:运行应用的环境可能会使用较新的.NET运行时,这可能会更改应用行为。

启动依赖于框架的应用

有两种方法可以运行依赖框架的应用:通过特定于平台的可执行文件(“apphost”)和通过 dotnet myapp.dll。 可以直接运行 apphost 可执行文件,而不是调用 dotnet myapp.dll,这仍然是运行应用的可接受方法。 建议尽可能使用 apphost。 使用 apphost 有很多优点:

  • 可执行文件看起来像本地平台标准的可执行文件。
  • 可执行名称保留在进程名称中,这意味着可以根据应用的名称轻松识别应用。
  • 由于 apphost 是本机二进制文件,因此可以将清单等本机资源附加到其上。
  • Apphost 默认应用了低级别安全缓解措施,使其更安全。 例如,从 .NET 9 开始,默认启用控制流强制技术(CET)阴影堆栈。 针对 dotnet 采取的缓解措施是所有受支持运行时环境的最低标准。

发布

dotnet publish -c Release [-r <RID>]
  • -c Release

    此开关将生成配置设置为 Release,该版本已针对生产部署进行优化。

  • -r <RID>

    此开关使用运行时标识符(RID)来指定目标平台,并确保包含本机依赖项(如果需要)。 有关运行时标识符的列表,请参阅 运行时标识符(RID)目录。

或者明确地:

dotnet publish -c Release [-r <RID>] --self-contained false
  • --self-contained false

    此开关明确告知 .NET SDK 创建依赖于框架的部署。

  1. 右键单击 解决方案资源管理器 中的项目,然后选择 Publish。
  2. 如果这是首次发布,请选择 “文件夹 ”作为发布目标,然后选择“ 下一步”。
  3. 选择文件夹位置或接受默认值,然后选择“ 完成”。
  4. 在发布配置文件中,选择“ 显示所有设置”。
  5. 将 部署模式 设置为 依赖框架 (这是默认值)。
  6. 将 Target Runtime设置为所需的平台(例如,64 位Windows的 win-x64)。
  7. 选择“ 保存 ”,然后选择 “发布”。

配置 .NET 安装搜索行为

默认情况下,apphost 会发现并使用全局安装的.NET运行时,安装位置因平台而异。 有关运行时发现和安装位置的详细信息,请参阅 排查应用启动失败问题。

还可以根据每个执行自定义.NET运行时路径。 环境变量 DOTNET_ROOT 可用于指向自定义位置。 有关所有 DOTNET_ROOT 配置选项的详细信息,请参阅 .NET 环境变量。

一般情况下,使用 DOTNET_ROOT 最佳做法是:

  1. 首先清除 DOTNET_ROOT 环境变量,这意味着以文本 DOTNET_ROOT开头的所有环境变量。
  2. 将 DOTNET_ROOT 且仅将 DOTNET_ROOT 设置为目标路径。
  3. 执行目标 apphost。

在 .NET 9 及更高版本中,可以通过 AppHostDotNetSearch 和 AppHostRelativeDotNet 属性配置已发布可执行文件的.NET安装搜索路径。

AppHostDotNetSearch允许指定可执行文件查找.NET安装的一个或多个位置:

  • AppLocal:应用可执行文件的文件夹
  • AppRelative:相对于应用可执行文件的路径
  • EnvironmentVariable:环境变量的值DOTNET_ROOT[_<arch>]
  • Global: 已注册 和 默认 的全局安装位置

AppHostRelativeDotNet 指定相对于可执行文件的路径,当 AppHostDotNetSearch 包含 AppRelative 时将会进行搜索。

有关详细信息,请参阅 AppHostDotNetSearch、AppHostRelativeDotNet 以及 apphost 中的安装位置选项。

跨平台 DLL 部署

或者,可以将应用发布为跨平台 DLL,而无需特定于平台的可执行文件。 在此模式下,会在发布输出文件夹中创建一个 myapp.dll 文件。 若要运行应用,请导航到输出文件夹并使用 dotnet myapp.dll 命令。

要作为跨平台 DLL 发布:

dotnet publish -c Release -p:UseAppHost=false
  • -c Release

    此开关将生成配置设置为 Release,该版本已针对生产部署进行优化。

  • -p:UseAppHost=false

    此属性禁用创建特定于平台的可执行文件,只生成可移植 DLL。

  1. 右键单击 解决方案资源管理器 中的项目,然后选择 Publish。
  2. 如果这是首次发布,请选择 “文件夹 ”作为发布目标,然后选择“ 下一步”。
  3. 选择文件夹位置或接受默认值,然后选择“ 完成”。
  4. 在发布配置文件中,选择“ 显示所有设置”。
  5. 将 部署模式 设置为 依赖框架。
  6. 取消选中 “生成单个文件”。
  7. 将 目标运行时 设置为 可移植 (或留空)。
  8. 选择“ 保存 ”,然后选择 “发布”。

作为独立应用发布

发布独立部署(SCD)时,发布过程将创建特定于平台的可执行文件。 发布 SCD 包括运行应用所需的所有.NET文件,但不包括.NET的本机依赖项。 在应用运行之前,这些依赖项必须存在于环境中。

如果发布 SCD,则会创建一个不前滚到最新可用 .NET 安全补丁的应用。 有关编译时的版本绑定的详细信息,请参阅选择要使用的.NET版本。

优点

  • Control .NET 版本:控制随应用部署的.NET版本。
  • 特定于平台的目标:由于应用必须针对每个平台发布,因此很明显应用在何处运行。

缺点

  • 较大规模的部署:由于应用包含.NET运行时和所有依赖项,因此所需的下载大小和硬盘空间大于依赖于框架的部署。
  • 更难更新 .NET 版本:只能通过发布应用程序的新版本来升级 .NET 运行时。

提示

可以通过 发布精简版 或启用 全球化不变模式来减少兼容自包含应用的总大小。 有关全球化固定模式的详细信息,请参阅.NET全球化固定模式。

发布

dotnet publish -c Release -r <RID> --self-contained true
  • -c Release

    此开关将生成配置设置为 Release,该版本已针对生产部署进行优化。

  • -r <RID>

    此开关使用运行时标识符(RID)来指定目标平台,并确保包含本机依赖项(如果需要)。 有关运行时标识符的列表,请参阅 运行时标识符(RID)目录。

  • --self-contained true

    此开关告知 .NET SDK 将可执行文件创建为独立部署 (SCD)。

  1. 右键单击 解决方案资源管理器 中的项目,然后选择 Publish。
  2. 如果这是首次发布,请选择 “文件夹 ”作为发布目标,然后选择“ 下一步”。
  3. 选择文件夹位置或接受默认值,然后选择“ 完成”。
  4. 在发布配置文件中,选择“ 显示所有设置”。
  5. 将 部署模式 设置为 自包含模式。
  6. 将 Target Runtime设置为所需的平台(例如,64 位Windows的 win-x64)。
  7. 选择“ 保存 ”,然后选择 “发布”。

发布为单个文件

将应用发布为单文件部署时,所有依赖应用程序的文件都捆绑成单个二进制文件。 此部署模型适用于依赖于框架的应用程序和独立应用程序,提供一个有吸引力的选项,用于将应用程序部署和分发为单个文件。

单文件应用始终特定于 OS 和体系结构。 需要针对每个配置(例如 Linux x64、Linux Arm64、Windows x64 等)进行发布。

优点

  • 简化的分发:将应用程序部署和分发为单个可执行文件。
  • 减少了文件混乱:所有依赖项都捆绑在一起,无需管理多个文件。
  • 轻松部署:复制单个文件以部署应用程序。

缺点

  • 较大的文件大小:单个文件包含所有依赖项,使其大于单个文件。
  • 启动速度较慢:必须在运行时提取文件,这可能会影响启动性能。
  • 特定于平台:必须为每个目标平台发布单独的文件。

单文件部署可以与其他优化(例如 剪裁 和 ReadyToRun 编译 )结合使用,以便进一步优化。

有关单文件部署的详细信息,请参阅 单文件部署。

发布

dotnet publish -c Release -r <RID> -p:PublishSingleFile=true
  • -c Release

    此开关将生成配置设置为 Release,该版本已针对生产部署进行优化。

  • -r <RID>

    此开关使用运行时标识符(RID)来指定目标平台,并确保包含本机依赖项(如果需要)。 有关运行时标识符的列表,请参阅 运行时标识符(RID)目录。

  • -p:PublishSingleFile=true

    此属性将所有依赖应用程序的文件捆绑到一个二进制文件中。

  1. 右键单击 解决方案资源管理器 中的项目,然后选择 Publish。
  2. 如果这是首次发布,请选择 “文件夹 ”作为发布目标,然后选择“ 下一步”。
  3. 选择文件夹位置或接受默认值,然后选择“ 完成”。
  4. 在发布配置文件中,选择“ 显示所有设置”。
  5. 将 部署模式 设置为 自包含 模式或 依赖于框架。
  6. 将 Target Runtime设置为所需的平台(例如,64 位Windows的 win-x64)。
  7. 请选中 “生成单个文件”。
  8. 选择“ 保存 ”,然后选择 “发布”。

发布为本机 AOT

本机 AOT 部署将应用直接编译为本机代码,无需运行时。 此发布选项使用 自包含部署 模式,因为编译的本机代码必须包含运行应用程序所需的所有内容。 这会导致更快的启动时间和减少内存使用率,但对受支持的功能存在一些限制。

优点

  • 快速启动:运行时不需要 JIT 编译,导致应用程序启动速度更快。
  • 降低的内存使用:与传统.NET应用程序相比,内存占用量较低。
  • No 运行时依赖项:应用程序无需.NET运行时安装即可运行。
  • 较小的部署大小:通常比带有完整运行时的自包含部署更小。

缺点

  • Limited 框架支持:并非所有 .NET 特性和库都与原生 AOT 兼容。
  • 构建时间更长:编译为原生代码所需的时间比常规构建更长。
  • 特定于平台:必须为每个目标平台和体系结构单独编译。
  • 调试限制:与常规.NET应用程序相比,调试体验更为复杂。

有关本机 AOT 部署的详细信息,请参阅 本机 AOT 部署。

发布

dotnet publish -c Release -r <RID> -p:PublishAot=true
  • -c Release

    此开关将生成配置设置为 Release,该版本已针对生产部署进行优化。

  • -r <RID>

    此开关使用运行时标识符(RID)来指定目标平台,并确保包含本机依赖项(如果需要)。 有关运行时标识符的列表,请参阅 运行时标识符(RID)目录。

  • -p:PublishAot=true

    此属性启用本机 AOT 编译,该编译会将应用直接编译为本机代码。

项目文件中必须配置本机 AOT 发布。 无法通过Visual Studio发布 UI 启用它。

  1. 在 解决方案资源管理器 中,右键单击项目并选择Edit 项目文件。

  2. 将以下属性添加到 <PropertyGroup> 中:

    <PublishAot>true</PublishAot>
    
  3. 保存项目文件。

  4. 右键单击 解决方案资源管理器 中的项目,然后选择 Publish。

  5. 如果这是首次发布,请选择 “文件夹 ”作为发布目标,然后选择“ 下一步”。

  6. 选择文件夹位置或接受默认值,然后选择“ 完成”。

  7. 在发布配置文件中,选择“ 显示所有设置”。

  8. 将 部署模式 设置为 自包含模式。

  9. 将 Target Runtime设置为所需的平台(例如,64 位Windows的 win-x64)。

  10. 选择“ 保存 ”,然后选择 “发布”。

有关本机 AOT 部署的详细信息,请参阅 本机 AOT 部署。

作为 ReadyToRun 发布

使用 ReadyToRun 编译发布应用时,应用程序程序集将编译为 ReadyToRun (R2R) 格式。 R2R 是一种提前(AOT)编译形式,它通过减少实时(JIT)编译器在加载应用程序时所需的工作量来提高启动性能。 此发布选项可用于 依赖于框架 的部署模式和 独立 部署模式。

ReadyToRun 二进制文件包含中间语言(IL)代码以及相同代码的本机版本代码。 虽然 R2R 二进制文件大于常规程序集,但它们提供更好的启动性能。

优点

  • 改进了启动时间:应用在启动期间花费更少的时间运行 JIT 编译器。
  • 更好的首次使用性能:减少首次执行代码路径的延迟。
  • 与现有代码兼容:无需修改即可处理大多数.NET库和框架。
  • 灵活的部署:可以与 依赖于框架的部署 模式和 独立部署 模式结合使用。

缺点

  • 尺寸较大:应用在磁盘上的存储占用较大,因为包含 IL 和本地代码。
  • 生成时间越长:编译所需的时间比标准发布要长。
  • 特定于平台的优化:最佳性能提升需要面向特定平台。

发布

dotnet publish -c Release -r <RID> -p:PublishReadyToRun=true
  • -c Release

    此开关将生成配置设置为 Release,该版本已针对生产部署进行优化。

  • -r <RID>

    此开关使用运行时标识符(RID)来指定目标平台,并确保包含本机依赖项(如果需要)。 有关运行时标识符的列表,请参阅 运行时标识符(RID)目录。

  • -p:PublishReadyToRun=true

    此属性启用 ReadyToRun 编译,该编译通过预编译程序集来提高启动性能。

  1. 右键单击 解决方案资源管理器 中的项目,然后选择 Publish。
  2. 如果这是首次发布,请选择 “文件夹 ”作为发布目标,然后选择“ 下一步”。
  3. 选择文件夹位置或接受默认值,然后选择“ 完成”。
  4. 在发布配置文件中,选择“ 显示所有设置”。
  5. 将 部署模式 设置为 自包含 模式或 依赖于框架。
  6. 将 Target Runtime设置为所需的平台(例如,64 位Windows的 win-x64)。
  7. 检查 “启用 ReadyToRun 编译”。
  8. 选择“ 保存 ”,然后选择 “发布”。

有关 ReadyToRun 部署的详细信息,请参阅 ReadyToRun 编译。

容器部署

将应用发布为容器时,.NET SDK 会将应用程序及其依赖项打包到容器映像中,而无需单独的 Dockerfile。 此部署模式创建可在任何容器运行时(如 Docker 或 Podman)上运行的完整容器映像。 容器部署简化了容器化过程,无需编写和维护 Dockerfiles,同时提供优化的基映像。

从 .NET SDK 8.0.200 开始,容器支持默认包含,不需要额外的 NuGet 包。 对于控制台应用程序,可能需要通过将属性设置为 EnableSdkContainerSupporttrue 来显式启用容器支持。

提示

有关与容器相关的项目设置的详细信息,请参阅 Containerize .NET 应用参考。

优点

  • 简化的容器化:无需为基本方案编写或维护 Dockerfiles。
  • 优化的基础映像:使用具有最新安全更新的Microsoft提供的优化基础映像。
  • 一致的环境:确保跨开发、测试和生产一致的运行时环境。
  • 轻松分发:可在不同环境中轻松共享和部署容器映像。
  • 平台隔离:应用程序在隔离容器中运行,从而减少应用程序之间的冲突。

缺点

  • 容器运行时依赖项:目标环境必须安装容器运行时。
  • 映像大小:容器映像通常大于其他部署方法。
  • 学习曲线:需要了解容器概念和工具。
  • 有限的自定义:与自定义 Dockerfiles 在复杂场景中的应用相比,灵活性较低。

发布

dotnet publish -c Release [-r <RID>] /t:PublishContainer
  • -c Release

    此开关将生成配置设置为 Release,该版本已针对生产部署进行优化。

  • -r <RID>

    此开关使用运行时标识符(RID)来指定目标平台,并确保包含本机依赖项(如果需要)。 有关运行时标识符的列表,请参阅 运行时标识符(RID)目录。

  • -t:PublishContainer

    此目标将应用程序发布为容器映像。

也可以采用发布配置文件的方法:

dotnet publish -c Release [-r <RID>] -p:PublishProfile=DefaultContainer
  • -p:PublishProfile=DefaultContainer

    此配置文件将启动容器发布过程。

  1. 右键单击 解决方案资源管理器 中的项目,然后选择 Publish。
  2. 选择 容器注册表 作为发布目标,然后选择“ 下一步”。
  3. 选择目标容器注册表(如 Azure 容器注册表、Docker Hub 或 Generic Registry),然后选择 Next。
  4. 配置注册表连接详细信息和身份验证。
  5. 在发布配置文件中,选择“ 显示所有设置”。
  6. 根据需求将 部署模式 设置为 自包含 模式或依赖于 框架 。
  7. 将 目标运行时 设置为所需的平台(例如 Linux 容器的 linux-x64 )。
  8. 配置特定于容器的设置,例如映像名称和标记。
  9. 选择“ 保存 ”,然后选择 “发布”。

有关容器部署的详细信息,请参阅 .NET SDK 容器创建概述。

另请参阅