Windows authentication in Docker containers just got a lot easier

Windows authentication in Docker containers just got a lot easier

23. August 2018

Windows authentication in Docker containers just got a lot easier

Windows authentication in Docker containers is kind of a tricky subject and while containers in general are gaining momentum every day, containers on Windows are having a somewhat less steep increase and Windows authentication in that context is the niche in a niche. Still, that topic matters if you have users depending on Windows authentication that you want to bring to a containerized environment, so it is very good to see Microsoft making very nice improvements in that area.


If you want to use Windows authentication in Docker containers you need something called a group Managed Service Account or gMSA to handle the communication with your Active Directory. Until now there was a restriction that the name of the gMSA and the container needed to be the exact same. That meant that you had to create a gMSA for every new container and also that you had to remove the gMSA again after you removed the container. For a number of reasons that was bad, mostly because it prevented any meaningful dynamic scaling efforts through compose, Swarm1 or Kubernetes because you will end up with dynamic container names there and it meant that you couldn’t use standard tooling like portainer for those cases. With the latest Windows Server 2019 Insider Preview Microsoft announced that this restriction is no longer in place. I had to create a NAV/BC container image based on a matching Windows Server base image but because of Freddy Kristiansen’s excellent work this is quite easy now2. In the end I have verified that this indeed does work as advertised, you are free to name the gMSA however you want and you can reuse it between containers!

The glorious details

Microsoft’s release notes are actually quite clear on this topic but I have to admit that I completely missed that part and only was made aware of it when @marknitek was kind enough to politely tell me that I was wrong after I had3 said that I was quite sure I was right. A very good reminder that even in areas where I spent a lot of time and in this case did a lot of banging my head against a wall, there is always something new to learn… Anyways, the main point is that Microsoft announced that we no longer need the same name for the gMSA and the container:

Group Managed Service Accounts
We’ve improved the scalability and reliability of containers that use group managed service accounts (gMSA) to access network resources. You should see fewer authentication errors when using a single gMSA with multiple container instances. Additionally, you no longer need to set the container’s host name to be the same as the gMSA. We also fixed a bug that prevented you from using gMSAs with Hyper-V isolated containers.

I simply had to try that, so I went straight to the Insiders download page, got the ISO and as I needed full AD integration, asked my colleagues from Axians IT Solutions who are managing our base internal IT to provide a VM with that Insider version of Windows Server 2019. Running Windows containers with process isolation which I very much prefer requires the same base version for the container and the host, so I had to build my own NAV/BC image as we currently only have official images for 2016 LTSC. But that is quite easily done:

  1. A basic prereq obviously is Docker itself, so I followed the steps outlined here which are slightly different than installing in a non Insider version4. If you do that yourself, make sure to pull the correct version of the Insider container image as it otherwise won’t start. In my case this is the specific command I used:
    docker pull mcr.microsoft.com/windowsservercore-insider:10.0.17738.1000 
  2. The standard NAV/BC images are built on top of the .NET framework 4.7.2 runtime image for Server 2016 LTSC, so I needed to create one for my Server 2019 Insider build. With the way Microsoft is working these days it wasn’t a surprise to find the Dockerfile for that on Github with a 5 second search. I removed everything downloading and applying patches as those didn’t work on Server 2019 and ran docker build -t microsoft/dotnet-framework:4.7.2-runtime-windowsservercore-insider-10.0.17738.1000 . to get my base image.
  3. Because of the very flexible way the NAV/BC images are constructed, in the next step I needed a so called generic image. For that I cloned the nav-docker Github repo and slightly adjusted build.ps1 so that it didn’t try to push to the MS docker hub repo and built the image I wanted. The first five lines for me now look like this:
    $registry = ""
    $tag = ""
    $latest = $true
    "insider-10.0.17738.1000" | % {

    compared to the original found here. I also changed the Dockerfile to reference my base image instead of the 2016ltsc one (first line now is FROM microsoft/dotnet-framework:4.7.2-runtime-windowsservercore-insider-10.0.17738.1000)

  4. Now I only needed to install NAV into that base image and I went with the latest 2018 CU, which is 8. I downloaded the DVD, extracted it and created the following Dockerfile as a slight variation of the explanation here:
    FROM dynamics-nav:generic-insider-10.0.17738.1000
    COPY NAVDVD c:/navdvd
    RUN PowerShell .\Run\buildimage.ps1
    ENV DatabaseServer localhost
    ENV DatabaseName CRONUS

    With docker build -t dynamics-nav:2018-cu8-w1-insider . and a bit of patience I had my NAV 2018 Docker image based on Windows Server 2019 Insider Preview. Not a five minute job but also really not terribly complicated.

With that in place, the rest was a breeze: I created two containers, one named tstme2 and one tstme35, both using a gMSA named tst19 and both using Windows auth:

docker run --name tstme2 --hostname tstme2 --security-opt "credentialspec=file://tst19.json" --network MyTransparentNetwork -e auth=Windows -e usessl=n -e accept_eula=y dynamics-nav:2018-cu8-w1-insider
docker run --name tstme3 --hostname tstme3 --security-opt "credentialspec=file://tst19.json" --network MyTransparentNetwork -e auth=Windows -e usessl=n -e accept_eula=y dynamics-nav:2018-cu8-w1-insider

To make sure that I didn’t get access through the old „first user in the database always gets in“ mechanism, I created my own Windows user and that of a colleague as users in NAV and still SSO worked perfectly.

I have to say I was somewhat surprised to see Microsoft making that progress as I really hadn’t seen anything at all in that area despite a couple of Github issues and support cases. But it is a very pleasant surprise as this will drastically decrease complexity for running Windows Containers with Windows authentication and enable a couple of new scenarios, especially around dynamic scaling. More to follow…

  1. Jakub Vanak told me that this is actually not true and because I have learned to always trust Jakub, I absolutely believe him, will try that sooner rather than later and probably blog about it as well
  2. I still remember the nights spent to get NAV working inside of a container while we didn’t have Microsoft support for it (and I had about 5% of my current Docker knowledge, not because I know so much now but because I knew so little then :) )
  3. rather less politely
  4. I got an error about hyper-v, most likely because we don’t have nested virtualization enabled but as I wanted to use process isolation I didn’t need hyper-v and therefore ignored the error. Always a good recipe for disaster, but luckily not in this case
  5. as you can guess by those names, tstme1 was a botched attempt and I was too lazy to delete it