Fixing “hostfxr.dll could not be found” within Windows Docker container (.NET installed from dotnet-install.ps1)
This is here mostly for my own reference for next time I need to fix this, but may be useful to someone else.
Installing .NET (5, Core, etc.) via the Microsoft Supplied “dotnet-install.ps1″(https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-install-script) installs the frameworks fine, but then running .net core code within that windows container would sometimes yield an error like
A fatal error occurred, the required library hostfxr.dll could not be found. If this is a self-contained application, that library should exist in [C:\Users\ContainerAdmin\....omitted path..\]. If this is a framework-dependent application, install the runtime in the default location [C:\Program Files\dotnet] or use the DOTNET_ROOT environment variable to specify the runtime location.
The problem here is that whilst the framework is installed, its not only installed into the ContainerAdmin user directory by default (Meaning issues with ContainerUser running code), but also that neither the PATH nor DOTNET_SETUP system variables have been altered.
This can be confirmed by either running the images terminal in something like Portainer, or doing a docker exec, and simply typing
$env:DOTNET_ROOT into the terminal. The first will most likely not contain the .Net install location, and the latter will yield an empty/null result.
Quick fix / Proving the issue
To prove this is the case, we can simply execute the command(s):
$env:Path += ";C:\Users\ContainerAdministrator\AppData\Local\Microsoft\dotnet\" $env:DOTNET_ROOT = "C:\Users\ContainerAdministrator\AppData\Local\Microsoft\dotnet\"
and now, if the library is installed it should run the .net code fine.
My next step was adding these to their own PowerShell file to be included and ran (as per above) as part of my Dockerfile build. It seems that whilst this code executes during docker build, it doesn’t actually set the paths correctly though. Maybe it is linked to the library being installed into users? Either way it didn’t want to work unless I executed the code manually. (Someone feel free to correct me on this!)
Changing default installation & Setting paths via Dockerfile
I think there are 2 issues here. One is that the dotnet library is being installed into a users directly, and the other is that the paths are not being set properly.
Changing the install location
When running dotnet-install.ps1, we can pass an
InstallDir parameter through. I suggest a commonly accessible location like “C:\Dotnet”, so that the command looks like:
\dotnet-install.ps1 -Channel Current -runtime aspnetcore -InstallDir "C:\dotnet"
Changing the environmental variables within the Dockerfile
By making use of the
SET /M command.
RUN setx /M PATH $($Env:PATH + ';C:\dotnet') RUN setx /M DOTNET_ROOT 'C:\dotnet'
The first will append the install location to the path (Hence the ; at the start), and the second will set the DOTNET_ROOT variable.
Now rebuilding your image should ensure the framework is globally accessible.
Hopefully this helps someone as I spent too long and waded through too many similar github issue tickets before finding the full solution!
A snippet from the Dockerfile below for reference: