This browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
Note
Access to this page requires authorization. You can trysigning in orchanging directories.
Access to this page requires authorization. You can trychanging 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, seeTutorial: Publish a .NET console application using Visual Studio Code.
For a short tutorial on publishing, seeTutorial: Publish a .NET console application using Visual Studio.
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.
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 an optional 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.
Important
You specify the target platform with a runtime identifier (RID). For more information about RIDs, see.NET RID Catalog.
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 validTarget 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 isRelease, unless changed with the-c parameter.
dotnet publish -c Release -f net9.0The default output directory of thedotnet 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, seeArtifacts output layout.
In Visual Studio, create separate publishing profiles for each target framework.
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 ("apphost") alongside the portable DLL unless you explicitly disable this behavior.
The platform-specific executable is created because of theUseAppHost property, which defaults totrue. To publish only the portable DLL without the platform-specific executable, setUseAppHost tofalse either on the command line (-p:UseAppHost=false) or as aproject property.
The benefit of targeting a specific platform is that it can handlenative dependencies that your app might require, ensuring compatibility with the target platform's specific requirements.
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, seeRuntime Identifier (RID) catalog.
For a list of runtime identifiers, seeRuntime Identifier (RID) catalog.
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 is the default mode when you publish from either the CLI or Visual Studio. In this mode, a platform-specific executable is created that can be used to start your app. The platform-specific executable is named something similar tomyapp.exe on Windows or justmyapp on other platforms.
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, seeSelect the .NET version to use.
Advantages
Disadvantages
There are two ways to run framework-dependent apps: through the platform-specific executable ("apphost") and viadotnet myapp.dll. You can run the apphost executable directly instead of callingdotnet myapp.dll, which is still an acceptable way to run the app. Whenever possible, it's recommended to use the apphost. There are a number of advantages to using the apphost:
dotnet are the lowest common denominator of all supported runtimes.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, seeRuntime 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.
By default, the apphost discovers and uses a globally installed .NET runtime, with install locations varying by platform. For more information about runtime discovery and install locations, seeTroubleshoot app launch failures.
The .NET runtime path can also be customized on a per-execution basis. TheDOTNET_ROOT environment variable can be used to point to the custom location. For more information about allDOTNET_ROOT configuration options, see.NET environment variables.
In general, the best practice for usingDOTNET_ROOT is to:
DOTNET_ROOT environment variables first, meaning all environment variables that start with the textDOTNET_ROOT.DOTNET_ROOT, and onlyDOTNET_ROOT, to the target path.In .NET 9 and later versions, you can configure the .NET installation search paths of the published executable via theAppHostDotNetSearch andAppHostRelativeDotNet 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 anddefault global install locationsAppHostRelativeDotNet specifies the path relative to the executable that will be searched whenAppHostDotNetSearch containsAppRelative.
For more information, seeAppHostDotNetSearch,AppHostRelativeDotNet, andinstall location options in apphost.
Alternatively, you can publish your app as a cross-platform DLL without a platform-specific executable. In this mode, amyapp.dll file is created in the publish output folder. To run your app, navigate to the output folder and use thedotnet myapp.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.
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, seeSelect the .NET version to use.
Advantages
Disadvantages
Tip
You can reduce the total size of compatible self-contained apps bypublishing trimmed or by enablingglobalization invariant mode. For more information about globalization invariant mode, see.NET Globalization Invariant Mode.
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, seeRuntime Identifier (RID) catalog.
--self-contained true
This switch tells the .NET SDK to create an executable as a self-contained deployment (SCD).
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
Disadvantages
Single-file deployment can be combined with other optimizations liketrimming andReadyToRun compilation for further optimization.
For more information about single-file deployment, seeSingle-file deployment.
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, seeRuntime Identifier (RID) catalog.
-p:PublishSingleFile=true
This property bundles all application-dependent files into a single binary.
Native AOT deployment compiles your app directly to native code, eliminating the need for a runtime. This publishing option usesself-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
Disadvantages
For more information about Native AOT deployment, seeNative AOT deployment.
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, seeRuntime 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.
InSolution Explorer, right-click on your project and selectEdit Project File.
Add the following property to a<PropertyGroup>:
<PublishAot>true</PublishAot>Save the project file.
Right-click on the project inSolution Explorer and selectPublish.
If this is your first time publishing, selectFolder as the publish target and selectNext.
Choose a folder location or accept the default, then selectFinish.
In the publish profile, selectShow all settings.
SetDeployment Mode toSelf-contained.
SetTarget Runtime to your desired platform (for example,win-x64 for 64-bit Windows).
SelectSave and thenPublish.
For more information about Native AOT deployment, seeNative AOT 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 bothframework-dependent andself-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
Disadvantages
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, seeRuntime Identifier (RID) catalog.
-p:PublishReadyToRun=true
This property enables ReadyToRun compilation, which improves startup performance by pre-compiling assemblies.
For more information about ReadyToRun deployment, seeReadyToRun compilation.
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 theEnableSdkContainerSupport property totrue.
Tip
For more information about project settings related to containers, seeContainerize a .NET app reference.
Advantages
Disadvantages
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, seeRuntime 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.
For more information about container deployment, see.NET SDK container creation overview.
Was this page helpful?
Need help with this topic?
Want to try using Ask Learn to clarify or guide you through this topic?
Was this page helpful?
Want to try using Ask Learn to clarify or guide you through this topic?