最近はまた Windows Server Containers の実運用に関して、いろいろと考えたり調べたりしているのですが、Windows では絶対に避けられないものとして Windows Update があります。
そして現時点での Windows Server Containers には以下のような要件があります。
Windows Server コンテナーは、ビルド番号が異なると起動をブロックされます (例: 10.0.14300.1030 (Technical Preview 5) と 10.0.14393 (Windows Server 2016 RTM))。 ビルド番号が一致し、リビジョン番号が異なる場合は、起動をブロックされません (例: 10.0.14393 (Windows Server 2016 RTM) と 10.0.14393.206 (Windows Server 2016 GA))。 ただし、技術的にはブロックされませんが、これは状況によっては正しく機能しない可能性がある構成であるため、運用環境ではサポートできません。
Windows コンテナーの要件 | Microsoft Docs
ドキュメントの内容を解釈すると、Windows Server Containers ではリビジョンまでホストとコンテナのバージョンを一致させないと、正しく動かない可能性があるし運用環境では実質使えないということでしょう。
ここで Docker の罠が出てくるわけです。普通に microsoft/windowsservercore と指定すると latest タグのイメージが落ちてくるので、リビジョンはその時の最新になり固定できません。現時点では面倒でもタグまでちゃんと指定するべきということなのでしょう。
# Windows Server Core のイメージを利用する FROM microsoft/windowsservercore:10.0.14393.953 # IIS までインストールされたイメージを利用する FROM microsoft/iis:windowsservercore-10.0.14393.953 # ASP.NET 4.6.2 までインストールされたイメージを利用する FROM microsoft/aspnet:4.6.2-windowsservercore-10.0.14393.953
当然ながら Windows Update でリビジョンが変わった場合には、同様に変更する必要があります。
オンプレの仮想環境であれば、自分でバージョンやアップデートのタイミングをある程度決められるので latest でも良いかもしれないですが、Azure や AWS の場合は少し注意が必要そうです。
Azure の場合
Azure にある Windows Server 2016 with Containers を利用すると、予め Windows Server Core と Nano Server が pull された状態で起動することが出来ますが、タグが latest になっているので扱いにくいです。
最近の Windows Server Core だと多少は差分が利用されるみたいなので、5GB 落とし直しにはならないみたいですが時間はかかります。
Dockerfile で latest を指定したイメージを実行しようとすると、イメージを作成した時点での latest になるので奇跡的にバージョンが一致していないと pull し直しになってしまいそうです。
ある意味公式である Azure VM のイメージがこれだと、正直なところ不安になってきます。
AWS の場合
EC2 の Windows Server 2016 Base with Containers ではイメージが pull されていないので、そのまま ECS のベースイメージとして使うと全てのインスタンスで pull が走ってしまって時間がかかります。
予め pull 済みの AMI を作っておいた方が良さそうです。User Data で pull と sysprep までやらせます。
function Get-OSVersion() { $buildLabEx = (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\').BuildLabEx $osBuild = $buildLabEx.Substring(0, $buildLabEx.IndexOf(".", 6)) return "10.0." + $osBuild } docker pull microsoft/windowsservercore:$(Get-OSVersion) docker pull microsoft/iis:windowsservercore-$(Get-OSVersion) docker pull microsoft/aspnet:4.6.2-windowsservercore-$(Get-OSVersion) docker pull microsoft/nanoserver:$(Get-OSVersion) docker pull microsoft/iis:nanoserver-$(Get-OSVersion) cd "$env:ProgramData\Amazon\EC2-Windows\Launch\Scripts" .\InitializeInstance.ps1 -Schedule .\SysprepInstance.ps1
ホストとコンテナのバージョンは合わせる必要があるので、頑張ってレジストリから取得するようにしています。ECS クラスターを作成するのは面倒だったので、普通に EC2 のインスタンスを立ち上げました。
docker images を実行すると、各ベースとなるイメージが pull 済みになっているのが確認できます。
AMI で用意されている Windows Server 2016 のバージョンと同じになっていることも確認できました。
課題としては Windows Update のタイミングでリビジョンが上がるという点ですが、こればっかりは Windows Update の時に AMI を作り直して入れ替えるぐらいしかない気がしました。
リビジョンをまで指定しないといけないのは非常に扱いにくいですが、カーネルを共有している以上仕方ない部分だと思いました。docker pull が賢くなればましになるかもしれないですが、今はこれで精いっぱい。