Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
This article explains the different ways to publish a .NET application. It covers publishing modes, how to produce executables and cross-platform binaries, and the impact of each approach on deployment and runtime environments. You can publish .NET applications using either the .NET CLI or Visual Studio.
For a short tutorial on publishing, see Tutorial: Publish a .NET console application using Visual Studio Code.
For a short tutorial on publishing, see Tutorial: Publish a .NET console application using Visual Studio.
What is publishing
Publishing a .NET app means compiling source code to create an executable or binary, along with its dependencies and related files, for distribution. After publishing, you deploy the app to a server, distribution platform, container, or cloud environment. The publishing process prepares an app for deployment and use outside of a development environment.
Publishing modes
There are two primary ways to publish an app. Some factors that influence this decision include whether the deployment environment has the appropriate .NET Runtime installed and whether you need specific compilation features that require bundling the runtime with your app. The two publishing modes are:
Publish self-contained
This mode produces a publishing folder that includes a platform-specific executable used to start the app, a compiled binary containing app code, any app dependencies, and the .NET runtime required to run the app. The environment that runs the app doesn't need to have the .NET runtime preinstalled.Publish framework-dependent
This mode produces a publishing folder that includes a platform-specific executable used to start the app, a compiled binary containing app code, and any app dependencies. The environment that runs the app must have a version of the .NET runtime installed that the app can use. An optional platform-specific executable can be produced.
Important
You specify the target platform with a runtime identifier (RID). For more information about RIDs, see .NET RID Catalog.
Publishing basics
The <TargetFramework>
setting of the project file specifies the default target framework when you publish your app. You can change the target framework to any valid Target Framework Moniker (TFM). For example, if your project uses <TargetFramework>net9.0</TargetFramework>
, a binary that targets .NET 9 is created.
If you want to target more than one framework, you can set the <TargetFrameworks>
setting to multiple TFM values, separated by a semicolon. When you build your app, your app is built for each target framework defined by your project. However, when you publish your app, you must specify the target framework:
The default build configuration mode is Release, unless changed with the -c
parameter.
dotnet publish -c Release -f net9.0
The default output directory of the dotnet publish
command is ./bin/<BUILD-CONFIGURATION>/<TFM>/publish/
. For example, dotnet publish -c Release -f net9.0
publishes to ./bin/Release/net9.0/publish/
. However, you can opt in to a simplified output path and folder structure for all build outputs. For more information, see Artifacts output layout.
In Visual Studio, create separate publishing profiles for each target framework.
Portable binaries
When you publish a .NET app, you can target a specific platform or create a portable binary. By default, even when creating a portable binary, .NET publishes a platform-specific executable alongside the portable DLL unless you explicitly disable this behavior.
The platform-specific executable is created because of the UseAppHost
property, which defaults to true
. To publish only the portable DLL without the platform-specific executable, set UseAppHost
to false
either on the command line (-p:UseAppHost=false
) or as a project property.
The benefit of targeting a specific platform is that it can handle native dependencies that your app might require, ensuring compatibility with the target platform's specific requirements.
Native dependencies
If your app has native dependencies, it might not run on a different operating system if published as a portable binary. For example, apps that depend on the Windows API don't natively run on macOS or Linux. You would need to provide platform-specific code and compile an executable for each platform.
Consider also, if a library you referenced provides platform-specific dependencies, your app might not run on every platform. However, when you publish and target a specific platform, the platform-specific dependencies of a NuGet package are copied to the publish folder.
To ensure that your app is published with its native dependencies, publish for a specific platform:
dotnet publish -c Release -r <RID>
-c Release
This switch sets the build configuration to Release, which is optimized for production deployment.
-r <RID>
This switch uses a runtime identifier (RID) to specify the target platform and ensures native dependencies are included (if required). For a list of runtime identifiers, see Runtime Identifier (RID) catalog.
- Right-click on the project in Solution Explorer and select Publish.
- If this is your first time publishing, select Folder as the publish target and select Next.
- Choose a folder location or accept the default, then select Finish.
- In the publish profile, select Show all settings.
- Set Target Runtime to your desired platform (for example, win-x64 for 64-bit Windows).
- Select Save and then Publish.
For a list of runtime identifiers, see Runtime Identifier (RID) catalog.
Quick reference
The following table provides quick examples of how to publish your app.
Publish Mode | Command |
---|---|
Framework-dependent deployment | dotnet publish -c Release [-r <RID>] |
Framework-dependent deployment (DLL) | dotnet publish -c Release -p:UseAppHost=false |
Self-contained deployment | dotnet publish -c Release [-r <RID>] --self-contained true |
Single-file deployment | dotnet publish -c Release [-r <RID>] -p:PublishSingleFile=true |
Native AOT deployment | dotnet publish -c Release [-r <RID>] -p:PublishAot=true |
ReadyToRun deployment | dotnet publish -c Release [-r <RID>] -p:PublishReadyToRun=true |
Container deployment | dotnet publish -c Release [-r <RID>] -t:PublishContainer |
Framework-dependent deployment
Framework-dependent deployment is the default mode when you publish from either the CLI or Visual Studio. In this mode, a platform-specific executable host is created to host your cross-platform app. The host executable filename varies per platform and is named something similar to <PROJECT-FILE>.exe
. You can run this executable directly instead of calling dotnet <PROJECT-FILE>.dll
, which is still an acceptable way to run the app.
Your app is configured to target a specific version of .NET. That targeted .NET runtime is required to be on the environment where your app runs. For example, if your app targets .NET 9, any environment that your app runs on must have the .NET 9 runtime installed.
Publishing a framework-dependent deployment creates an app that automatically rolls forward to the latest .NET security patch available on the environment that runs the app. For more information on version binding at compile time, see Select the .NET version to use.
Advantages
- Small deployment: Only the app and its dependencies are distributed. The environment where the app is run must already have the .NET runtime installed.
- Cross-platform: The app and any .NET-based library runs on other operating systems.
- Uses the latest patched runtime: The app uses the latest runtime installed in the environment.
Disadvantages
- Requires pre-installing the runtime: The app can run only if the version of .NET it targets is already installed in the environment.
- .NET might change: The environment where the app is run might use a newer .NET runtime, which could change app behavior.
Publish
dotnet publish -c Release [-r <RID>]
-c Release
This switch sets the build configuration to Release, which is optimized for production deployment.
-r <RID>
This switch uses a runtime identifier (RID) to specify the target platform and ensures native dependencies are included (if required). For a list of runtime identifiers, see Runtime Identifier (RID) catalog.
Or explicitly:
dotnet publish -c Release [-r <RID>] --self-contained false
--self-contained false
This switch explicitly tells the .NET SDK to create a framework-dependent deployment.
- Right-click on the project in Solution Explorer and select Publish.
- If this is your first time publishing, select Folder as the publish target and select Next.
- Choose a folder location or accept the default, then select Finish.
- In the publish profile, select Show all settings.
- Set Deployment Mode to Framework-dependent (this is the default).
- Set Target Runtime to your desired platform (for example, win-x64 for 64-bit Windows).
- Select Save and then Publish.
Configure .NET install search behavior
In .NET 9 and later versions, you can configure the .NET installation search paths of the published executable via the AppHostDotNetSearch
and AppHostRelativeDotNet
properties.
AppHostDotNetSearch
allows specifying one or more locations where the executable will look for a .NET installation:
AppLocal
: app executable's folderAppRelative
: path relative to the app executableEnvironmentVariable
: value ofDOTNET_ROOT[_<arch>]
environment variablesGlobal
: registered and default global install locations
AppHostRelativeDotNet
specifies the path relative to the executable that will be searched when AppHostDotNetSearch
contains AppRelative
.
For more information, see AppHostDotNetSearch
, AppHostRelativeDotNet
, and install location options in apphost.
Cross-platform DLL deployment
Alternatively, you can publish your app as a cross-platform DLL without a platform-specific executable. In this mode, a <PROJECT-NAME>.dll
file is created in the publish output folder. To run your app, navigate to the output folder and use the dotnet <PROJECT-NAME>.dll
command.
To publish as a cross-platform DLL:
dotnet publish -c Release -p:UseAppHost=false
-c Release
This switch sets the build configuration to Release, which is optimized for production deployment.
-p:UseAppHost=false
This property disables the creation of a platform-specific executable, producing only the portable DLL.
- Right-click on the project in Solution Explorer and select Publish.
- If this is your first time publishing, select Folder as the publish target and select Next.
- Choose a folder location or accept the default, then select Finish.
- In the publish profile, select Show all settings.
- Set Deployment Mode to Framework-dependent.
- Uncheck Produce single file.
- Set Target Runtime to Portable (or leave blank).
- Select Save and then Publish.
Self-contained deployment
When you publish a self-contained deployment (SCD), the publishing process creates a platform-specific executable. Publishing an SCD includes all required .NET files to run your app but it doesn't include the native dependencies of .NET. These dependencies must be present on the environment before the app runs.
Publishing an SCD creates an app that doesn't roll forward to the latest available .NET security patch. For more information on version binding at compile time, see Select the .NET version to use.
Advantages
- Control .NET version: Control which version of .NET is deployed with the app.
- Platform-specific targeting: Because the app must be published for each platform, it's clear where the app runs.
Disadvantages
- Larger deployments: Because the app includes the .NET runtime and all dependencies, the download size and hard drive space required is greater than a framework-dependent deployment.
- Harder to update the .NET version: The .NET Runtime can only be upgraded by releasing a new version of the app.
Tip
You can reduce the total size of compatible self-contained apps by publishing trimmed or by enabling globalization invariant mode. For more information about globalization invariant mode, see .NET Globalization Invariant Mode.
Publish
dotnet publish -c Release -r <RID> --self-contained true
-c Release
This switch sets the build configuration to Release, which is optimized for production deployment.
-r <RID>
This switch uses a runtime identifier (RID) to specify the target platform and ensures native dependencies are included (if required). For a list of runtime identifiers, see Runtime Identifier (RID) catalog.
--self-contained true
This switch tells the .NET SDK to create an executable as a self-contained deployment (SCD).
- Right-click on the project in Solution Explorer and select Publish.
- If this is your first time publishing, select Folder as the publish target and select Next.
- Choose a folder location or accept the default, then select Finish.
- In the publish profile, select Show all settings.
- Set Deployment Mode to Self-contained.
- Set Target Runtime to your desired platform (for example, win-x64 for 64-bit Windows).
- Select Save and then Publish.
Single-file deployment
When you publish your app as a single-file deployment, all application-dependent files are bundled into a single binary. This deployment model is available for both framework-dependent and self-contained applications, providing an attractive option to deploy and distribute your application as a single file.
Single-file apps are always OS and architecture specific. You need to publish for each configuration, such as Linux x64, Linux Arm64, Windows x64, and so forth.
Advantages
- Simplified distribution: Deploy and distribute your application as a single executable file.
- Reduced file clutter: All dependencies are bundled, eliminating the need to manage multiple files.
- Easy deployment: Copy a single file to deploy the application.
Disadvantages
- Larger file size: The single file includes all dependencies, making it larger than individual files.
- Slower startup: Files must be extracted at run time, which can impact startup performance.
- Platform-specific: Must publish separate files for each target platform.
Single-file deployment can be combined with other optimizations like trimming and ReadyToRun compilation for further optimization.
For more information about single-file deployment, see Single-file deployment.
Publish
dotnet publish -c Release -r <RID> -p:PublishSingleFile=true
-c Release
This switch sets the build configuration to Release, which is optimized for production deployment.
-r <RID>
This switch uses a runtime identifier (RID) to specify the target platform and ensures native dependencies are included (if required). For a list of runtime identifiers, see Runtime Identifier (RID) catalog.
-p:PublishSingleFile=true
This property bundles all application-dependent files into a single binary.
- Right-click on the project in Solution Explorer and select Publish.
- If this is your first time publishing, select Folder as the publish target and select Next.
- Choose a folder location or accept the default, then select Finish.
- In the publish profile, select Show all settings.
- Set Deployment Mode to Self-contained or Framework-dependent.
- Set Target Runtime to your desired platform (for example, win-x64 for 64-bit Windows).
- Check Produce single file.
- Select Save and then Publish.
Native AOT deployment
Native AOT deployment compiles your app directly to native code, eliminating the need for a runtime. This publishing option uses self-contained deployment mode, as the compiled native code must include everything needed to run the application. This results in faster startup times and reduced memory usage, but comes with some limitations on supported features.
Advantages
- Fast startup: No JIT compilation needed at run time, leading to faster application startup.
- Reduced memory usage: Lower memory footprint compared to traditional .NET applications.
- No runtime dependency: The application runs without requiring .NET runtime installation.
- Smaller deployment size: Often smaller than self-contained deployment with the full runtime.
Disadvantages
- Limited framework support: Not all .NET features and libraries are compatible with Native AOT.
- Longer build times: Compilation to native code takes longer than regular builds.
- Platform-specific: Must compile separately for each target platform and architecture.
- Debugging limitations: More complex debugging experience compared to regular .NET applications.
For more information about Native AOT deployment, see Native AOT deployment.
Publish
dotnet publish -c Release -r <RID> -p:PublishAot=true
-c Release
This switch sets the build configuration to Release, which is optimized for production deployment.
-r <RID>
This switch uses a runtime identifier (RID) to specify the target platform and ensures native dependencies are included (if required). For a list of runtime identifiers, see Runtime Identifier (RID) catalog.
-p:PublishAot=true
This property enables Native AOT compilation, which compiles the app directly to native code.
Native AOT publishing must be configured in the project file. You can't enable it through the Visual Studio publishing UI.
In Solution Explorer, right-click on your project and select Edit Project File.
Add the following property to a
<PropertyGroup>
:<PublishAot>true</PublishAot>
Save the project file.
Right-click on the project in Solution Explorer and select Publish.
If this is your first time publishing, select Folder as the publish target and select Next.
Choose a folder location or accept the default, then select Finish.
In the publish profile, select Show all settings.
Set Deployment Mode to Self-contained.
Set Target Runtime to your desired platform (for example, win-x64 for 64-bit Windows).
Select Save and then Publish.
For more information about Native AOT deployment, see Native AOT deployment.
ReadyToRun deployment
When you publish your app with ReadyToRun compilation, your application assemblies are compiled as ReadyToRun (R2R) format. R2R is a form of ahead-of-time (AOT) compilation that improves startup performance by reducing the amount of work the just-in-time (JIT) compiler needs to do as your application loads. This publishing option can be used with both framework-dependent and self-contained deployment modes.
ReadyToRun binaries contain both intermediate language (IL) code and the native version of the same code. While R2R binaries are larger than regular assemblies, they provide better startup performance.
Advantages
- Improved startup time: The app spends less time running the JIT compiler during startup.
- Better first-use performance: Reduced latency for first-time execution of code paths.
- Compatible with existing code: Works with most .NET libraries and frameworks without modification.
- Flexible deployment: Can be combined with both framework-dependent deployment and self-contained deployment modes.
Disadvantages
- Larger size: The app is larger on disk due to including both IL and native code.
- Longer build times: Compilation takes more time than standard publishing.
- Platform-specific optimizations: Best performance gains require targeting specific platforms.
Publish
dotnet publish -c Release -r <RID> -p:PublishReadyToRun=true
-c Release
This switch sets the build configuration to Release, which is optimized for production deployment.
-r <RID>
This switch uses a runtime identifier (RID) to specify the target platform and ensures native dependencies are included (if required). For a list of runtime identifiers, see Runtime Identifier (RID) catalog.
-p:PublishReadyToRun=true
This property enables ReadyToRun compilation, which improves startup performance by pre-compiling assemblies.
- Right-click on the project in Solution Explorer and select Publish.
- If this is your first time publishing, select Folder as the publish target and select Next.
- Choose a folder location or accept the default, then select Finish.
- In the publish profile, select Show all settings.
- Set Deployment Mode to Self-contained or Framework-dependent.
- Set Target Runtime to your desired platform (for example, win-x64 for 64-bit Windows).
- Check Enable ReadyToRun compilation.
- Select Save and then Publish.
For more information about ReadyToRun deployment, see ReadyToRun compilation.
Container deployment
When you publish your app as a container, the .NET SDK packages your application and its dependencies into a container image without requiring a separate Dockerfile. This deployment mode creates a complete container image that can be run on any container runtime, such as Docker or Podman. Container deployment simplifies the containerization process by eliminating the need to write and maintain Dockerfiles while providing optimized base images.
Starting with .NET SDK 8.0.200, container support is included by default and doesn't require extra NuGet packages. For console applications, you might need to enable container support explicitly by setting the EnableSdkContainerSupport
property to true
.
Tip
For more information about project settings related to containers, see Containerize a .NET app reference.
Advantages
- Simplified containerization: No need to write or maintain Dockerfiles for basic scenarios.
- Optimized base images: Uses Microsoft-provided, optimized base images with the latest security updates.
- Consistent environment: Ensures consistent runtime environment across development, testing, and production.
- Easy distribution: Container images can be easily shared and deployed across different environments.
- Platform isolation: Applications run in isolated containers, reducing conflicts between applications.
Disadvantages
- Container runtime dependency: The target environment must have a container runtime installed.
- Image size: Container images are typically larger than other deployment methods.
- Learning curve: Requires understanding of container concepts and tooling.
- Limited customization: Less flexibility compared to custom Dockerfiles for complex scenarios.
Publish
dotnet publish -c Release [-r <RID>] /t:PublishContainer
-c Release
This switch sets the build configuration to Release, which is optimized for production deployment.
-r <RID>
This switch uses a runtime identifier (RID) to specify the target platform and ensures native dependencies are included (if required). For a list of runtime identifiers, see Runtime Identifier (RID) catalog.
-t:PublishContainer
This target publishes the application as a container image.
You can also use the publish profile approach:
dotnet publish -c Release [-r <RID>] -p:PublishProfile=DefaultContainer
-p:PublishProfile=DefaultContainer
This profile triggers the container publishing process.
- Right-click on the project in Solution Explorer and select Publish.
- Select Container Registry as the publish target and select Next.
- Choose your target container registry (such as Azure Container Registry, Docker Hub, or Generic Registry) and select Next.
- Configure the registry connection details and authentication.
- In the publish profile, select Show all settings.
- Set Deployment Mode to Self-contained or Framework-dependent based on your needs.
- Set Target Runtime to your desired platform (for example, linux-x64 for Linux containers).
- Configure container-specific settings like image name and tags.
- Select Save and then Publish.
For more information about container deployment, see .NET SDK container creation overview.