I have been struggling to get dotnet build to work on nanoserver via docker. I had already given up on git, because I can perform git tasks outside the container first.

Basically I was trying this:

docker run -v "$(pwd):C:/work" -w C:/work -it --rm microsoft/dotnet:1.1.1-sdk-nanoserver powershell build.ps1

This maps the current repository directory to a folder called work on the container, and runs the build inside it. This approach means:

  • a) All software dependencies are isolated inside the container (including which version of the dotnet cli tools are installed); and
  • b) All resulting files are available on the host machine afterwards.

The problem is this:

C:\Program Files\dotnet\sdk\1.0.1\Microsoft.Common.CurrentVersion.targets(1111,5): error MSB3644: The reference assemblies for framework ".NETFramework,Version=v4.5" were not found. To resolve this, install the SDK or Targeting Pack for this framework version or retarget your application to a version of the framework for which you have the SDK or Targeting Pack installed. Note that assemblies will be resolved from the Global Assembly Cache (GAC) and will be used in place of reference assemblies. Therefore your assembly may not be correctly targeted for the framework you intend. [C:\work\project\MyProject\MyProject.csproj]

Basically, this docker image is “microsoft/dotnet:1.1.1-sdk-nanoserver”, which is docker image targeting windows NanoServer and contains the dotnet core 1.1.1 tools (current latest, first with *.csproj capability). This image does not contain the full .Net framework (among other things).

Now I could have decided to use microsoft/dotnet-framework which is built on microsoft/windowsservercore and includes full .Net. However, that is a 4GB base image with another 1Gb image applied on top. Very large.

This lead me to try a few different things to fix the error on this image, eventually finding the magic combo I needed:

-e "ReferenceAssemblyRoot=C:\NetReference" -v "C:/Program Files (x86)/Reference Assemblies\Microsoft\Framework:C:/NetReference"

Essentially I map the Reference Assemblies folder to the container as well. Then I use the (rather undiscoverable) Environment Variable ReferenceAssemblyRoot to point to that folder. That folder on my machine looks like:

 |-- .NETCore
 |    +-- ...
 |-- .NETFramework
 |    |-- v3.5
 |    |   +-- ...
 |    |-- v4.0
 |    |   +-- ...
 |    |-- v4.5
 |    |   +-- ...
 |    |-- v4.5.1
 |    |   +-- ...
 |    |-- ...
 |-- .NETPortable
 |    +-- ...
 |-- Silverlight
 |    +-- ...
 |-- v3.0
 |    +-- ...
 +-- v3.5
      +-- ...

Basically, every target framework sdk I have installed on the machine.

And for building libraries, this is all you need.

The full final command is:

docker run -e "ReferenceAssemblyRoot=C:\NetReference" -v "C:/Program Files (x86)/Reference Assemblies\Microsoft\Framework:C:/NetReference" -v "$(pwd):C:/work" -w C:/work -it --rm microsoft/dotnet:1.1.1-sdk-nanoserver powershell build.ps1

Just make sure that you have the required frameworks on your machine already (which might be your laptop or (in my case) a TeamCity Agent with Windows Docker installed and configured.