Dotnet Core 3.0 deployment models

Dotnet Core 3.0 deployment models

Published on: 20 October 2020

Author: Ramesh Kanjinghat

With dotnet core version 3.0 and later we have 2 models to deploy or publish executables; Framework Dependent and Self-contained.
Framework dependent was the only option we had until Dotnet Core 3.0. We have to have the runtime installed on the machine where the executable runs on. There are lot of benefits with this approach like generate cross-platform binaries, lighter executable size, one runtime installation can be shared by multiple applications on the same machine, easy runtime upgrades etc.
Self-contained is a new option that Dotnet Core 3.0 and later versions support. With this approach the executable carries the runtime along wherever it goes. Because the executable carries the runtime along, you find hundreds, if not thousands of files in the same folder where the executable is.
There are 3 File Publish Options to further optimize the assemblies.
  • Produce single file
  • Enable ReadyToRun compilation
  • Trim unused assemblies
We won’t be talking much about Enable ReadyToRun compilation here. Simply put, this option does ahead-of-time (AOT) compilation thus reduces the time it takes to load the application on its very first run. Lot of JIT work will be done while compilation itself. Richard Lander talks about this option in detail https://devblogs.microsoft.com/dotnet/announcing-net-core-3-0-preview-6/
Produce single fileEnable ReadyToRunTrim unused
Framework dependentYesYesNo
Self-containedYesYesYes
I will try to walk you through the process while I verify these options one-by-one. I will do this by creating a simple console application that writes “Hello World” on the console.
Application details
  • Let us call it HelloWorld.
  • We will use latest dotnet core version which is 3.1.
  • We will use Visual studio 2019 for development and deployment.
  • We will also add Newtonsoft.Json as an external, I mean non-runtime, dependency.
I assume you know how to publish an executable to folder in Visual Studio. This https://docs.microsoft.com/en-us/dotnet/core/tutorials/publishing-with-visual-studio could be a good reference.
Now we will examine both these deployment models with applicable File Publish options.
First, we will start with Framework dependent option.
Framework dependent profile settings screenshot
Framework dependent profile settings screenshot
FRAMEWORK DEPENDENT (FILE PUBLISH OPTIONS: NONE): I have published the executable with both File Publish Options not selected.
Fact Check: Now let’s examine the publish folder. It has just 6 files and is 853 KB.
Famework dependent publish folder with no Publish File options selected
Famework dependent publish folder with no Publish File options selected
** FRAMEWORK DEPENDENT (WITH FILE PUBLISH OPTION, PRODUCE SINGLE FILE): I have published the executable with both File Publish Options not selected.
Fact Check: You can notice below screenshot that there are just 2 files and it is 853 KB. Other than file count we don’t gain anything else.older. It has just 6 files and is 853 KB.
Framework dependent publish folder with Publish File option Publish single file
Framework dependent publish folder with Publish File option Publish single file
Now we will look into the second deployment model, Self-contained with the File Publish options, Trim unused assemblies and Produce single file. In the below screenshot you can see that Deployment Mode is “Self-Contained”.
Self-contained deployment model profile settings
Self-contained deployment model profile settings
SELF-CONTAINED (FILE PUBLISH OPTIONS: NONE): Initially I keep all the 3 File Publish Options un checked. As usual I have deleted the whole bin directory.
Fact Check: You can notice below screenshot that there are 226 files and it is 67 MB. That is gigantic compared to Framework-dependent. But we know this time the publish folder also has all the runtime assemblies.
You can also notice that I have highlighted assemblies System.IO.dll and Newtonsoft.Json.dll. We will compare this with later deployments to see what changed.
Self-contained publish folder with no File Publish options selected
Self-contained publish folder with no File Publish options selected
SELF-CONTAINED (FILE PUBLISH OPTIONS: PRODUCE SINGLE FILE): This time I have checked “Produce single file” checkbox.
Fact Check: There are just 2 files and the size is almost same, 66.7 MB. As you can see the executable is what taking up the all most all the memory except 1 KB.
Self-contained publish folder with Publish single file File Publish option
Self-contained publish folder with Publish single file File Publish option
SELF-CONTAINED (FILE PUBLISH OPTIONS: TRIM UNUSED ASSEMBLIES): Uncheck“Publish single file” and check “Trim unused assemblies” option.
Fact Check: There are just 112 files and the size came down to 35.2 MB. That is considerable optimization as we have saved close to 50% of memory.
Now if you compare the files with files produced by Self-contained (File Publish options: None) you will notice that System.IO.dll assembly is gone so has other 113 files. So, the compiler removes all those files which the application doesn’t need. The only exception is the external dependencies. We can find Newtonsoft.Json.dll assembly in the folder in spite of it never being used in our application.
Self-contained publish folder with Publish single file File Publish option
Self-contained publish folder with Publish single file File Publish option
SELF-CONTAINED (FILE PUBLISH OPTIONS: PRODUCE SINGLE FILE AND TRIM UNUSED ASSEMBLIES): Now check both “Produce single file” and “Trim unused assemblies”.
Fact Check: As expected Trim unused assemblies option removed all unused assemblies and then Produce single file option combined all files and produced a single executable file.
Self-contained publish folder with both Publish single file and Trim unused files File Publish options
Self-contained publish folder with both Publish single file and Trim unused files File Publish options
Tidbits
  1. One major disadvantage of Self-contained deployment model is the lack of cross-platform support. This is because the Target Runtime of this executable is decided at the time of publish so that it can carry all the dependencies along.
  2. As of writing this blog IIS doesn’t support single file deployments. Dotnet 5 is expected to support this feature.
  3. We can further trim the single executable file size with warp. Please check my write up on warp dotnet for more details. https://www.dhrutara.com/blogs/warp-it/