Reading Time: 3 minutes

Docker: NuGet Server Windows Server Core

I’ve set up a NuGet Server on a Dockerized Windows Server Core IIS image. This is a multi-stage build that includes an MSBuild stage to compile NuGet Server (ASP.NET) and copy that into the final image. The Dockerfile installs useful utilities like Chocolatey and Vim.

GitHUb: Docker NuGet Server Windows Core

Also, if you’re looking for a more modern NuGet server that runs in .NET Core on Linux… Check out BaGet.

GitHub: BaGet

Get Started

Make sure you are running Windows Containers.

git clone [email protected]:mrjamiebowman-blog/Docker-NuGet-Server-Windows-Core.git
cd Docker-NuGet-Server-Windows-Core
cd nugetserver
./build.ps1
./run.ps1

You can access the container by running this command.

docker exec -it nugetserver powershell

MSBuild Image

There are 2 Dockerfiles in this solution. The first Dockerfile in the msbuild folder was used to figure out how to create a build server that could compile ASP.NET 4.5 since NuGet Server is older code.

Some key takeaways here are, I had to use and create a FolderProfile.pubxml file to get this to publish to the correct path, and use a PowerShell script to wrap the msbuild command.

When the msbuild command is ran it causes an enormous amount of output to the screen which returns a non zero response. This causes the Docker build to fail. I was able to over come this by wrapping that process in a PowerShell script.

Publishing with MSBuild

At first, I tried several things like running the msbuild command with parameters. This didn’t go so well. Then I tried creating an msbuild script which ultimately was difficult when it came time to compile and publish the ASP.NET code. The easiest way for me was to create a FolderProfile.pubxml file.

MSBuild Command

msbuild NuGet.Server.sln /t:Rebuild /p:Configuration=Release /v:minimal
msbuild NuGet.Server.sln /p:DeployOnBuild=true /p:PublishProfile=FolderProfile

FolderProfile.pubxml

NuGet Server Image

Everything above is included in the Dockerfile that builds the NuGet Server.

Issues & Challenges

I ran into a few odd issues getting this to work.

ASP.NET 4.5

ASP.NET 4.5 is not installed by default on the IIS image. However, DotNet core is installed. I was able to get past that by running the command below.

Web.config Issues

I ran into a lot of issues with IIS and the web.config file. There were several sections of the web.config that were locked. To unlock them I had to run commands against the appcmd.exe.

RUN & $env:windir\system32\inetsrv\appcmd.exe unlock config -section:system.webServer/handlers
RUN & $env:windir\system32\inetsrv\appcmd.exe unlock config -section:system.webServer/modules

Enabling Directory Browsing

This was useful for debugging and you might need this at some point.

RUN & $env:windir\system32\inetsrv\appcmd set config /section:directoryBrowse /enabled:true

Viewing Errors

IIS will not display errors to the user. There are several ways to overcome this but I found this to be the easiest. While accessing the box and invoking a web request I was able to see the errors.

Invoke-WebRequest 'http://localhost/'

https://github.com/mrjamiebowman-blog/Docker-NuGet-Server-Windows-Core/blob/master/nugetserver/Dockerfile

Configuring the NuGet Server

API Keys

It’s important to protect your NuGet Server. I would recommend putting this on a private network behind a firewall of some sort but even then someone could push malicious code to the repository. The web.config has 2 keys that can be modified to enforce an API key policy: “requireApiKey“, and “apiKey“.

Docker Volumes

Being that this is a stateless image it’s important to map in a volume to manage the package data. There is a configuration key in the web.config for changing the package path; search for “packagesPath”.

Restarting IIS Site

IIS by default will reload the web.config once all connections drop but if you can’t wait run this command below.

Stop-IISSite -Name 'Default Web Site'
Start-IISSite -Name 'Default Web Site'