A Windows Container Guide for Linux Folks

Windows containers?

A Windows Container Guide for Linux Folks
Docker Client & Server on Windows Server 2016

Windows containers?

You may have heard about Windows containers for a while now. How could you not have? I knew something was up between Docker and Microsoft, but until the Christmas break, I didn’t really know much about it. I didn’t really get it. Did it just mean running Docker on a Windows laptop or server? How can you possibly implement Windows containers? How cross-compatible was Docker compatible across Linux and Window container implementations? What did Hyper/V have to do with it? What did this have to do with Open Sourcing .NET, if anything? How was this related to Windows Nano? And so on. But last week a AWS ECS Announcement for Windows container support announcement piqued by interest and got me digging in once I saw there were Windows Server 2016 AMIs “for containers.”

As an Ops guy (and a long time fan/user of OpenVZ, LXC, and even Solaris Zones) I was slow to get on the Docker bandwagon. I still think there is a lot of Kool Aid (and me-too-ism) out with regard to Docker. People think Docker will magically get them to “DevOps.” But I get it. There are use cases (and teams) that it makes sense (and many that don’t, especially if you already have reasonably robust full-stack configuration management) but when it comes to Windows containers, call me developer!

Honestly, I don’t want to learn or use Microsoft tools. I don’t even want to think about trying to get an Open Source config management (Ansible in particular) working on Windows. All I care about is getting an app to reliably deploy across multiple environments. I don’t want to come up with a packaging approach. It want it to just work, Sound familiar? Yeah, all the same arguments for Docker, than in an odd way make more sense on Windows than for Linux.

What I learned

So I did a lot of reading and video watching and here is some of what I learned. There is a lot interesting work going on here. It was interesting to hear how Microsoft actually made changes to the OS to support containers and adopted the conventions (and basic architecture) of Linux. We certainly have come a long way from the 1990s.

Windows images (unlike Linux) don’t include the whole OS. It shouldn’t have been a surprise, but unlike on Linux containers (whether Docker or LXC) you are not getting the whole OS filesystem. You are just getting hooks (think like symlinks) back to the host OS.

Microsoft has implemented some sort of “Union filesystem” for tracking individual file differences across images, but because Windows only support two main filesytems (NTFS and something else I had never heard of) this was actually a much easier task. Also Windows containers track changes to individual files vs. at the block level like Docker.

Windows containers on Windows 10 actually use Hyper/V and run in “isolation mode by default, unlike containers on Windows Server 2016. There is an “isolation” option that can be used to start the container.

There are two official base images for Windows: Windows Nano and Windows Server Core. OK, I lied. There are also images for IIS and SQL Server Express. As you can see they are big!

Windows Server 2016 only runs Windows containers for now. You cannot pull or run Linux images. Well Duh. Containers share the same kernel.

Don’t install Docker with the .msi if you are on Windows Server 2016, but simply download the Docker client and server binaries. It won’t even work. Don’t bother with all the GUI stuff.

IIS is a beast. Pulling the microsoft/iis image took several minutes and was nearly 9GB. But starting the container is still just as fast.

Docker is Docker. It is in Golang. It has the same command-line switches as the Linux version.

Windows Contaidners implement similar networking as Linux with a virtual switch and NATting.

Microsoft has open sourced their container compute shim that is written in Go.

(If I misinterpreted or forgot some of what I watched please feel free to correct me!)

Digging In

First things first, I started with a t2.medium but found installing the various packages I wanted via Chocolatey (like Visual Studio 2015) was too slow, so I switched to a c4.large. On this instance type, after installing the base images, performance was pretty snappy, but I really wasn’t doing much besides starting and stopping containers and poking around.

At first, I ran the version of Docker (October 11 build of 1.12) that was installed in the “Container” version of Windows Server 2016. It installs as a service, runs in the background, and sends logs to Windows Event Log. I wouldn’t bother with this approach if you are learning how stuff works. And given container support is still pretty recent, you are probably going to have to update Docker a lot anyway.

Download the latest release and just run server from the command line. Better yet, turn on debugging so you can see what it is really doing and see interesting stuff like what happens behind when you stop and delete a container.

Stopping and deleting a container

Inside “Program Files/Docker” you won’t fun much except except for the client and server, but if you browse into ProgramData you’ll see some of what is in “/var/lib/docker” on a Linux host.

“/var/lib/docker” on Windows

So let’s run some containers. What is interesting is that only the IIS image actually runs a process “ServerMonitor.exe w3svc” so it stays running while the smaller images stop. You will also not be able to run IIS interactively with the “-ti” option, like you can with the Nano or Windows Server Core images.

The Windows Server Core image has many of the standard services you would expect

Whereas the Nanoserver is running a few less processes, but interestingly enough as “AppXSvc” and “DeviceInstall” and there are a few others. I couldn’t find any super-detailed comparison between the two images except the Core image was “more compatible”

In general most of the commands work as you would expect except that instead of bash you are running cmd.exe or PowerShell and the usual strange Microsoft-isms, that I don’t get. I did seem to create more “dead” containers on Windows Server than on Linux, but restarting dockerd cleaned these up.

I’m going to continue playing around and I have a project where I’m hoping to get some developers deploying some simple (Windows-only) services running on either Core or Nano, so wish me luck, because I know I’m just scratching the surface here.

For more info

A Comparative Study of Docker Engine on Windows Server Vs Linux Platform (October 2016)

Windows Container Internals (November 2016)

Windows Server & Docker (July, 2016)