Windows Server Container に関して調べたこと

## この記事で書きたいこと

Windows Server 2016以降、OSの標準の機能[^feature]でWindows Serverをコンテナとして実行することができる。
2018年9月時点の状況として、上記の技術が実運用に耐えうる仕様であるか、また実用における課題として何が残っているのかを整理したい。

[^feature]: 厳密には、標準機能で提供されるのはコンテナをホストのプロセスから分離する技術部分のみで、コンテナの作成と実行にはDockerエンジンとクライアントをインストールする必要がある。[この記事（＠IT）](http://www.atmarkit.co.jp/ait/articles/1610/24/news014.html)にて非常にわかりやすく説明している。

逆に、コンテナ技術の一般的な内容についてはここでは記述しない。
また、Windowsにおけるコンテナホスト側の独自技術として、Hyper-Vによる分離という技術を有し、内部的に同社の仮想化技術であるHyper-Vを用いて、コンテナホスト側のカーネルとは独立してコンテナを実行することができる。しかし、実行時のメモリのフットプリントが通常のコンテナと比べて極めて大きくなること、また実行するコンテナにライセンスが必要になる(ただし、Standardでは初めから2コンテナ分のライセンスがホストに付帯)ことから、ここではあえて除外して説明する。


## 著者の知識レベルについて

Linuxコンテナを実運用で使ったことや、そもそもコンテナ技術に触れるのがWindows Server Containerが初。ただいま勉強中。


## 初めに結論

Windows Server 上でWindows Serverをコンテナとして実運用で稼働するには、現状で次の課題があり、これらのデメリットを熟慮したうえで採否を検討する必要がある。

+ Windows Server 2016上で実行するコンテナは、ホスト側とのOSのバージョン互換性がシビア。

+ Linuxのコンテナと比較してファイルサイズが大きい。

+ WindowsベースのDockerイメージやDockerfileが少ない。





## それぞれの課題について


### ホストとコンテナのバージョン互換性

Windows Serverのバージョンは下記のように4つのレベルでバージョンが表現される。

```
<メジャーバージョン>.<マイナーバージョン>.<ビルドバージョン>.<リビジョン>
```

このうち、Windows Server 2016をホストあるいはコンテナとする場合、リビジョンまでをホストとコンテナで一致させる必要があるが、リビジョン番号は、Windows UpdateなどでHotfixを適用するたびにインクリメントされてしまう。このため、セキュリティ上のリスクを鑑みて適宜Hotfixを適用していかなければならない実運用環境では、活用場面がかなり制限されている。


[Windows コンテナーの要件](https://docs.microsoft.com/ja-jp/virtualization/windowscontainers/deploy-containers/version-compatibility)




### コンテナイメージのファイルサイズ

LinuxのAlpine Linuxイメージ5MB前後と比較すると、Windows Serverのベースイメージはまだまだ大きい。

| イメージ | サイズ |
|:-:|:-:|
| Windows Server Core  | 10GB  |
| Windows Nano Server | 1.05GB |


### Windows系のコンテナイメージ不足

RDBMSなど、主要なミドルウェアを構築したい思ったとき、Linux上のコンテナ環境であれば、Docker Hubから信頼できるイメージ（通常は各ミドルウェアベンダー公式のイメージ）をダウンロード(pull)してきてすぐにデプロイができる。
これは、Linuxの各ディストリビューションとその上で動作するコンテナイメージの間に相互の互換性があるためである。このようなことが可能な理由としては、Linuxのカーネルシステムのインタフェース(ABI: Application Binary Interface)が変更されないよう長期に渡って厳格に保守されてきたバックグラウンドがあるためと考えられる。

一方で、WindowsはLinuxとは全く異なるカーネルを実装しており、さらにはWindows同士であってもカーネルの互換性というのはこれまで積極的に維持されていないことは、ホストとコンテナのバージョン互換性のところで述べた通りである。
Windowsのカーネルシステムのインタフェースについては、非公開かつプロプライエタリな仕様を貫いており、機能拡張やHotfixなど同社の都合でバージョン間の互換性が犠牲にされてきたことが想像される。現時点ではWindows Server環境で動作するコンテナイメージは限られており、Docker Hubでイメージが見つけられない場合は、自身でイメージの作成を行う必要があり、Linux環境と比較して手間がかかる。

筆者は試しにWindows Server Core上で動くPostgreSQLのイメージを作るためのDockerfileを書いてみたが、インストールから設定ファイルの変更まですべてシェルで操作しなければならず、何度かTry&Errorを繰り返すことになり、なかなか面倒だった。


## 課題に対する考えや今後の対策


### ホストとコンテナのバージョン互換性

Windows Server 2016 の半期チャネル(SAC)の一つであるWindows Server Version 1709からは、リビジョンの一致が不要となるため、Windows UpdateなどによるHotfixの適用についてコンテナとバージョンを同期させる必要がなくなる。
よって、この課題については、Windows Server Version 1709以降を採用することで、解決することが可能と考えられる。

また、本投稿で触れなかったHyper-Vによる分離を利用してコンテナを起動すれば、Windows Server 2016上においてもバージョンの互換性を気にせず運用することが可能ではある。



### コンテナイメージのファイルサイズ

これについても、Windows Server Version 1709から、Nano Serverのイメージサイズが80MBになり、大幅にサイズが改善されている。（Alpine Linuxがさらにその先を行ってしまっている感があるが、Ubuntuイメージが100MB程度であることを考えると、相当頑張っているというのが所感）

ただし、Nano Serverについては、.NET FrameworkやPowerShellが入っていないため、これらが必要な場合はWindows Server Coreのイメージを採用することになる。
未確認だが1709でServer Coreのイメージが60%軽量化されたとの情報があるため、数百MB程度のサイズにまで縮小されたと予想される。

[2018/10/05 追記]
実際にpullして確認してみたところ、1709のServer Coreのイメージサイズは6.44GBでした。（元が10GBなので、数百MBという期待は過剰でした。。）


### Windows系のコンテナイメージ不足

Windows Server Version 1709から、実験的リリースの位置づけではあるがLCOW (Linux Containers on Windows)という機能が実装されている。
何ができるかを先に説明すると、Windows Server環境にてWindows Serverコンテナと一緒にLinuxコンテナを実行できる仕組みである。

これは、内部的にはHyper-Vによる分離を使ってLinuxカーネル(Alpine Linuxが使われている模様)を起動し、その上でPullしてきてたLinuxイメージをコンテナとして実行しているようである。

上記が可能になれば、PostgreSQLやMySQLなどの環境をすぐに構築することができる。



## Windows Server 2019への期待

Windows Server 1709で多くの課題が解決してきているが、1709は長期サポートチャネル(LTSC)ではないため、サポート期間が18か月と短い。よって、Windows Serverにおけるコンテナ実運用の本命は、次期のLTSCであるWindows Server 2019になる。
タイムリーな話題として、本稿執筆の数日前にMicrosoftからWindows Server 2019の10月リリースが発表された。LCOWが正式な機能としてリリースされることが期待されるため、実行時のメモリやCPU消費など確認したい。


## 参考にさせていただいたページ
(整理中)