Docker on Windows
Posted in container on January 11, 2017 by Adrian Wyssmann ‐ 8 min read
Everyone loves docker even Microsoft embraces docker.
Back in September Docker and Microsoft announced the commercial partnership to extend Docker Engine to Windows Server. This is interesting, then so far Docker was available for Linux only. Sure, you could install the Docker Toolbox on Windows, but this solution uses boot2docker is a lightweight Linux distribution based on Tiny Core Linux. So the images that run in containers still use a Linux-based host and therefore you cannot run native Windows applications.
This is a is a huge limitation for usage of Docker for x-platform development and deployment so for example if you would like to run or test your asp.net application in an IIS. With the support of native Windows applications in Docker running on Windows 10 Pro, Enterprise and Education (1511 November update, Build 10586 or later). To do so you need to download and install Docker for Windows.
As on my work computer I still run Windows 7 I try to run Docker for Windows on a VM running in Virtualbox. Unfortunately I just get this error:
Trying to run within powershell I get another error:
A search in internet brings me to the this thread which one of the responses is
Since Docker for Windows also uses virtualisation the underlying system needs to support nested virtualisation. We have no control nor visibility on how the Windows VM is configured nor how well the various hypervisors support nested virtualisation (it’s very hard to get right) so we can’t really support this scenario.
So I create an VM in azure and follow the steps found in this blog to install Docker on the machine, which works without hassle. So running docker version
shows me
Running docker containers
Now I can run a windows based docker image.
What happens if I try to run a windows based docker image on Linux or vice versa? Well as docker images are bound to the host system a windows based image will not run under Windows and actually return an error docker: unknown blob
As on Linux, you can also create interactive sessions for instance by running docker run -it microsoft/nanoserver powershell
which results in a running container:
You can also mount data volumes. For this purpose I simply create a folder C:\test
on my Windows Server and create a file win2016_me.txt
within the folder. Now I can specify with -v
to map the data volume to e.g. C:\example
…
… and examine the content within the container
Cgroups, Namespaces and Overlay FS?
Linux uses kernel features like cgroups, kernel namespaces and an overlay file system for isolation. To support container in windows similar features are required and therefore required architectural changes which are only available from certain Windows versions (Windows 10 Anniversary Update, Some versions of Windows 2016 Server). This presentation gives some more insights into the architecture.
Generally Docker uses Job Objects a similar feature as cgroups for Linux
Job objects are namable, securable, sharable objects that control attributes of the processes associated with them. Operations performed on a job object affect all processes associated with the job object. Examples include enforcing limits such as working set size and process priority or terminating all processes associated with a job.
On the other hand we have the Object Namespaces which corresponds to kernel namespaces on Linux:
An object namespace protects named objects from unauthorized access. Creating a private namespace enables applications and services to build a more secure environment.
The last piece is the “Layer Capabilities” of the filesystem. Due to the amount of features provided by the NTFS, Microsoft decided not to completely build a new UFS layer for NTFS but rather provide use a hybrid approach. Each container gets it’s own virtual disk with NTFS file system and files are linked back to the source (on the host) via symlinks (also called reparse points). When files are changed these changes are the made persistent into the virtual block device. For the Windows registry on the other hand a true union FS was built to avoid cloning of full set of registry hives per container.
Types of containers
Windows container technology supports two types of containers: Windows Server-Container und Hyper-V-Container. Both are handled the same way and use the same images. The main difference is the degree of isolation according to this page
Windows Server containers: Multiple container instances can be run on a single host at the same time, using isolation technologies for namespaces, resource control, and processes. Windows Server containers share with each other and the same kernel with the host.
Hyper-V containers: Multiple container instances can run on one host at a time, but each container runs on a particular virtual machine. This results in isolation at the core level between each Hyper-V container and the container host.
https://docs.microsoft.com/en-us/virtualization/windowscontainers/manage-containers/hyperv-container actually give you a nice explication about the differences of the isolation. Windows Server containers share the same host and behave similar than containers on Linux. For example if we run a “ping” command within a container we actually can see the process running on the host system but we also see clearly that it has a “Job Object ID” associated - the same as the powershell which runs inside the container.
When running a Hyper-V container - started with parameter --isolation=hyperv
- the ping
process would be actually hidden from the host system. The difference to the “Windows Server Containers” is that instead a single shared kernel there is single shared hypervisor and multiple kernels on top. So for each container there is a separate VM instance running. The problem with VMs is the extra overhead required for each machine like the additional memory consumption or the relatively long startup for a VM. The Docker team addressed this issue with different measure in the implementation. To reduce the VM footprint Docker team create a small, stateless VM running a special Windows distribution containing only the necessary services and kernel configuration required to run containers - they call it “utility VM”.
In addition Docker takes advantage of how the access of the host file system is implemented. Hyper-V-Containers are using SMB protocol over the VMBus - a logical inter-partition communication channel to map portions of the host file system into the VM. This also enables to physically map portions of the executable into the VM so that they can be run from the file cache.
As a last piece they implemented a so called “cloning” functionality. As you can see in the image above the only thing that differs from Hyper-V Container to Hyper-V Container is the “Windows Server Container” part. All the rest, like the Windows Kernel or the Basic System Processes are the same for all VMs. Therefore to avoid duplication of memory, an initial VM is started. Once this is running, the memory state of the VM is freezed by pausing all virtual processes and shared. Now when a container is started, Docker forks the VM and use the shared memory state.
A quick demo of that can be found in the presentation at dockercon16.
Update 2019-09-25
Updated outdated links