Windows Server でのコンテナ/Docker アーキテクチャ

# はじめに
Windows Server 2016 TP3 で [Windows Server Containers と Docker Engine が使えるようになりました](http://qiita.com/Arturias/items/495a0ee338c0c8162541)が、そのアーキテクチャは Linux とは大きく異なるように見えます。

大きく違うのは、Linux では Docker Engine に実装されている以下の中心的な機能が、Windows では OS 側に実装されていることです。

* コンテナの制御(コンテナの作成、開始、停止など)
* イメージのファイルシステム管理

そのため、Windows では Docker Engine が無くてもコンテナの作成や実行ができます。このあたりのアーキテクチャを調べてみたので、推測込ですが以下にまとめてみます。

# アーキテクチャ概観
まず、Linux でのアーキテクチャを見て、Windows と比較してみます。

## Linux の場合
Docker Engine 内部では上位のロジックを実装している部分は Daemon と呼ばれ、実際にコンテナの制御を行う部分は Exec Driver や Exection Driver、イメージのファイルシステム管理を行う部分 Graph Driver や Storage Driver などと呼ばれています。

![DockerLinux.png](https://qiita-image-store.s3.amazonaws.com/0/79316/abf83a10-714a-da99-f076-c5e6a401a356.png)

Exec Driver や Graph Driver はプラグイン構造になっており、実際に処理を行うモジュール(ドライバ)を切り替えられるようになっています。

* Exec Driver  
  コンテナの制御を担当。かつては LXC が使われていたが、Docker 0.9 から native ドライバがデフォルト。native ドライバは、コンテナの実処理を行う libcontainer を呼び出している。
* Graph Driver  
  イメージのファイルシステム管理を担当。devicemapper や aufs など複数のドライバがある。

このように、Linux の場合は**コンテナ制御やイメージのファイルシステム管理は Docker Engine 内で行われます**。


## Windows の場合
Docker Engine 内の Exec Driver や Graph Driver という仕組み自体は変わらないのですが、**それらの実処理は hcsshim というモジュールを経由して OS 側で行われます**。

全体的なアーキテクチャとしては下図のようになっているようです。
![DockerWindows.png](https://qiita-image-store.s3.amazonaws.com/0/79316/d6644c05-402a-c140-240f-34e3e2fcf83c.png)

OS 側で処理を行うコンポーネントには Hyper-V という名前が付いていることから、Hyper-V のテクノロジーを利用しているのでしょう。このように処理の本体が OS 側にあるため、Docker Engine がなくても、PowerShell からコンテナの操作が可能になっています。

次に、Windows 上の各コンポーネントの役割をまとめてみます。

# Windows での各コンポーネントの役割

## Hyper-V Host Compute Service
Windows Server Containers の中心的な役割を担っていると思われるサービス。ファイルの実体は C:\windows\System32\vmcompute.exe。
![hcmsvc.png](https://qiita-image-store.s3.amazonaws.com/0/79316/2979701d-d757-91f4-85da-20b7f0986132.png)

このサービスの依存関係を見ると、以下の２つのカーネルドライバに依存していることが分かります。

**Windows Container Isolation**
名前から見て、カーネル側でコンテナを分離する機能(Linux でいう Namespaces相当？)を実装しているようです。
**Virtual Registry for Containers**
こちらも名前から見て、コンテナ間でレジストリを分離するための機能を実装しているようです。

![hcmsvc_drivers.png](https://qiita-image-store.s3.amazonaws.com/0/79316/f20266d7-5149-e68c-ab67-e40d13175756.png)

## Hyper-V Host Compute Service Library
Windows Server Containers の Win32 API を提供している DLL のようです。ファイルの実体は C:\windows\System32\vmcompute.dll です。

この DLL では、例えば以下のような API をエクスポートしており、これらは hcsshim 経由で Docker Engine から呼び出されています。

```text:コンテナ関連のAPI
CreateComputeSystem
StartComputeSystem
WaitForProcessInComputeSystem
ShutdownComputeSystem
TerminateComputeSystem
・・・
```

```text:ファイルシステム、ストレージ関連のAPI
CreateLayer
ActivateLayer
CopyLayer
CreateSandboxLayer
GetBaseImages
・・・
```

API 名をみると、Windows ではコンテナのことを ComputeSystem と呼んでいるんですかね。
なお余談ですが、この DLL を利用すれば、C++ や .NET から、Windows Server Containers を制御できるはずです。

## hcsshim
Docker Engine から Hyper-V Host Compute Service Library(vmcompute.dll) を呼び出すための橋渡しをするモジュールで、[ソースはGitHubで公開されてます](https://github.com/Microsoft/hcsshim)。

Go言語で書かれた Docker から Win32 API を呼び出すためにパラメータの形式変換などを行っており、vmcompute.dll を呼び出すためのラッパーと言っていいと思います。

ソースのコメントには以下のように書かれているので、Docker Engine から hcsshim 経由で Hyper-V Containers も管理できるようになるのでしょう。
> Shim for the Host Compute Service (HSC) to manage Windows Server
> containers and Hyper-V containers.

## Exec Driver の windows ドライバ
Windows Server 用の Exec Driver。hcsshim 経由で vmcompute.dll を呼び出しながら、コンテナの起動といった処理を上位の Daemon に提供してます。

## Graph Driver の windowsfilter/windowsdiff ドライバ
Windows Server 用の Graph Driver。Exec Driver と同じく、hcsshim 経由で vmcompute.dll を呼び出しながら、イメージのレイヤーの作成といった処理を上位の Daemon に提供してます。windowsfilter と windowsdiff の違いは不明。

なお、Exec Driver と Graph Driver(Storage Driver) は、```docker info``` コマンドで実際に使用されているドライバを見ることができます。
![DockerInfo.PNG](https://qiita-image-store.s3.amazonaws.com/0/79316/d0702abb-b2ef-207c-e08c-636aaa88be34.png)

# Docker Engine の役割
このようなアーキテクチャにより Windows では Docker Engine 無しでコンテナの作成や実行ができるわけですが、では Docker Engine の役割は何かというと、現状では Linux の Docker と同じ API やコマンド(run, ps, images ...)といったインターフェイスを提供することに見えます。

また、現在はまだ Docker イメージを使えないようなので(*1)、今後その辺の実装は Docker Engine 側に入ってくるのかもしれません。

*1) Windows では、windowsservercore という名前のイメージがデフォルトで登録されています。
![Images.png](https://qiita-image-store.s3.amazonaws.com/0/79316/000ef028-8f03-16e4-555f-68a1cfe09e53.png)

これらは、コンテナ環境を構築する[スクリプト]
(https://msdn.microsoft.com/virtualization/windowscontainers/quick_start/inplace_setup) を実行した際に、http://aka.ms/ContainerOSImage から **WIM(Windows イメージング)形式** のファイルがダウンロードされ、それが PowerShell の Install-ContainerOSImage Cmdlet によりインストールされたものです。