How to distribute a .NET Core application to users who don't have .NET Core installed

  • Case: .NET Core application for a wide user base
  • Problem: Users don’t have .NET Core installed
  • Solution: .NET Core self-contained deployments

I have a .NET Core Web Application that developers run locally. The problem is that most of the developers don’t have .NET Core installed on their development machines, so there needs to be a way that all developers can use the application without needing to install .NET Core.

Docker is normally a good option, but there is still plenty of developers who are not familiar with containers. Luckily .NET Core offers another solution, which allows developers to try .NET Core applications faster and without extra installations.

.NET Core Self-Contained Deployments

The .NET Core self-contained deployment has the application and all required third-party dependencies in a single folder, along with the version of .NET Core that is used to build the application. No installation or prerequisites are required from the user.

Downsides of self-contained deployments are that an own package is needed for each Operating System platform (win, osx, linux, …) and for each architecture (x64, x32, arm, …). E.g. win-x64, linux-x64. Before .NET Core 2.0 deployments had to define distribution and version, instead of platform, e.g. ubuntu-10.4-x64. Check available identifiers from .NET Core Runtime IDentifier (RID) catalog.

Deployment package size is still quite large, around 80MB, as lots of dlls are packed in that are not actually needed by the application. When the new Linker is released, package size should reduce significantly.

Setup

Modify csproj-file by adding RuntimeIdentifiers to the same PropertyGroup where the TargetFramework-element is. RuntimeIdentifiers must list all runtimes self-contained deployment is created.

This example has 3 runtime identifiers:

  • win-x64
  • osx-x64
  • linux-x64

PropertyGroup might also contain other elements that are not in the example below.

<PropertyGroup>
    <TargetFramework>netcoreapp2.0</TargetFramework>
    <RuntimeIdentifiers>win-x64;osx-x64;linux-x64</RuntimeIdentifiers>
</PropertyGroup>

Execute the publish-command from the command line.

$ dotnet publish -c release -r osx-x64
$ dotnet publish -c release -r linux-x64

Packages can be created for any runtime on any operating system, e.g. Linux and macOS deployments can be created on Windows machine and vice versa.

E.g. on .NET Core 2.0 linux-x64 files are published to the directory: \bin\release\netcoreapp2.0\linux-x64\publish

The root of the directory has files that are not needed for the self-contained deployment. The publish-folder contains all required files.

Note: When a package is released for Linux or macOS, it is recommended to archive files first with tar and then compress it with gzip. That is because of Unix pipelining philosophy. When releasing a package for Windows compress files with zip or 7zip.

Example csproj-file from FakeServer: FakeServer.csproj

Example release script-file from FakeServer: release.bat and release.sh

How To Use Self-Contained Deployments

In this example we use .NET Fake JSON Server’s binaries. Self-contained deployment archives have been uploaded to repository’s releases.

OS File name
macOs fakeserver-osx-x64.tar.gz
Linux fakeserver-linux-x64.tar.gz
Windows fakeserver-win-x64.7z

Commands for Linux users to download the file, unarchive the package and execute the binary. At the time of this post version 0.6.0 was the latest released version.

$ mkdir FakeServer && cd FakeServer
$ wget https://github.com/ttu/dotnet-fake-json-server/releases/download/0.6.0/fakeserver-linux-x64.tar.gz
$ tar -zxvf fakeserver-linux-x64.tar.gz
$ chmod +x FakeServer
$ ./FakeServer
Written on January 21, 2018