Learn through the super-clean Baeldung Pro experience:
>> Membership and Baeldung Pro.
No ads, dark-mode and 6 months free of IntelliJ Idea Ultimate to start with.
Last updated: September 3, 2025
In .NET development, the dotnet publish command is essential for preparing applications for distribution. It builds the application, processes its dependencies, and stores the finished distributable assets in a specific location. This tool supports a variety of deployment targets, such as folders, containers, and cloud environments.
In this tutorial, we’ll look at what dotnet publish does, how it works behind the scenes, and how to use it efficiently in various deployment circumstances.
When we run dotnet publish, the CLI executes several processes that change our source code into a production-ready package:
$ dotnet publish
In this example, when we run the command, the dotnet CLI starts converting the project to Intermediate Language (IL) assemblies. It then resolves all NuGet and project dependencies, ensuring that they work with the target framework. Following that, it moves the compiled binaries, configuration files, and static resources such as images or CSS to the publish folder.
In addition, when a runtime identifier is supplied, it contains the corresponding .NET runtime. Finally, it optimizes the files if trimming or single-file publication is selected.
The dotnet publish command provides numerous arguments and MSBuild attributes for customising the output.
These options allow us to specify the build configuration, target runtime, deployment model, and even how the files are packed. We can adapt a single codebase to many contexts by mixing different flags:
$ dotnet publish -c Release -o ./deploy
Determining projects to restore...
Restored /home/user/HelloApp/HelloApp.csproj (in 110 ms).
HelloApp -> /home/user/HelloApp/bin/Release/net8.0/HelloApp.dll
HelloApp -> /home/user/HelloApp/deploy/
In this example, the -c Release flag builds with optimisations, and the -o ./deploy flag directs the published files to a deploy folder rather than the typical publish location:
| Option | Description |
| -c <CONFIGURATION> | Specifies the build configuration, usually Debug or Release. Default is Debug. |
| -r <RUNTIME_IDENTIFIER> | Targets a specific OS and architecture, e.g., win-x64, linux-arm. |
| –self-contained true|false | Includes the .NET runtime in the output (true) or relies on the system runtime (false). |
| /p:PublishSingleFile=true | Bundles the app and dependencies into a single executable file. |
| /p:PublishTrimmed=true | Removes unused code from assemblies to reduce the size of the published output. |
| /p:PublishReadyToRun=true | Precompiles assemblies to improve application startup performance. |
| /p:PublishAot=true | Enables ahead-of-time (AOT) compilation where supported. |
| –no-restore | Skips restoring NuGet packages before publishing. |
| –no-build | Skips the build step and only performs publish actions (useful if the project is already built). |
| -o <OUTPUT_PATH> | Specifies the folder where the published files should be placed. |
These options allow us to fine-tune the publishing process for speed, portability, and size.
A framework-dependent deployment expects that the destination machine already has the .NET runtime installed. This keeps the published output small:
$ dotnet publish -c Release --self-contained false
HelloApp -> /home/user/HelloApp/bin/Release/net8.0/HelloApp.dll
HelloApp -> /home/user/HelloApp/bin/Release/net8.0/publish/
In this example, the publish folder contains mostly the application’s .dll file and any required libraries, but not the .NET runtime.
However, a self-contained deployment bundles the .NET runtime with the program, allowing it to execute on systems that don’t have .NET installed:
$ dotnet publish -c Release -r linux-x64 --self-contained true
HelloApp -> /home/user/HelloApp/bin/Release/net8.0/linux-x64/HelloApp.dll
HelloApp -> /home/user/HelloApp/bin/Release/net8.0/linux-x64/publish/
In this example, inspecting the publish folder displays an executable file as well as all runtime files required by that operating system and architecture.
Single-file publishing enables us to distribute an application, its dependencies, and, optionally, the .NET runtime as a single executable. This approach simplifies deployment by eliminating the need to handle numerous assemblies and runtime files:
$ dotnet publish -c Release -r win-x64 --self-contained true /p:PublishSingleFile=true
HelloApp -> C:\Projects\HelloApp\bin\Release\net8.0\win-x64\HelloApp.dll
HelloApp -> C:\Projects\HelloApp\bin\Release\net8.0\win-x64\publish\
In this example, we publish a single-file executable for Windows; once published, we inspect the publish folder and find only one .exe file along with a few runtime-dependent files, depending on the parameters.
We can then proceed to launch the executable:
$ C:\Projects\HelloApp\bin\Release\net8.0\win-x64\publish\HelloApp.exe
Hello World from Single File Deployment
This indicates that the application runs correctly from a single file. Single-file publishing considerably simplifies deployment by lowering the number of files to distribute. Instead of handling multiple assemblies and runtime libraries, we can provide a single executable that can be launched immediately.
Furthermore, this method is useful in situations when simplicity and portability are important, such as distributing desktop utilities or packaging applications into containers.
In conclusion, the dotnet publish command is a crucial step in transitioning an application from development to production. It compiles the source code, handles dependencies, and generates a deployment-ready package specific to the specified environment.
In this article, we discuss what happens when we publish and how using options like –self-contained, runtime identifiers, or single-file publishing provides us fine-grained control over how programs are generated and delivered.
Finally, framework-dependent deployments reduce the footprint but rely on the presence of the .NET runtime, whereas self-contained deployments ensure portability. Single-file publishing simplifies distribution by combining everything into a single executable.