Windows 11 ProでWindows Container を動かす

今の業務で開発しているアプリが、ファイルパスの関係で正常に動かすにはWindows上でアプリを動かす必要があった。これまでは直接ホスト上でアプリを動かしていたのだが、融通が利かないアプリなので、何かと開発環境に設定が必要で面倒に感じてきた。 仮想マシンで動かすことも考えたが、開発用VMだと定期的に環境の作り直しが発生するし、新しくWindowsのライセンスを用意するのも微妙な気がする。

そこで思い出したのはWindows Container。いわゆるDockerで動かすContainerのOSはLinuxになるが、WindowsをOSとしたContainerも存在する。あんまり流行ってなさそうだが。

自分が今使っているのはWindows 11 Proを使っている かつ 開発目的にしか使う想定が無いので、Windows Container環境的には問題なし。(運用で使うにはWindows Serverを使用しないとNGとのこと)
これまで一度も動かしたことが無かったので、これを機会に動かしてみた。

セットアップ

Prepare Windows operating system containers | Microsoft Learnや、Windows PCでDocker Desktopを利用せずにLinuxコンテナーとWindowsコンテナー環境を構築する方法 #Docker - Qiita を参考にセットアップをする。
Windows 11 Proの場合は、dockerを使う以外の方法は無いようだ。 Docker Desktopが推奨の方法だが有償化してしまったので、Install Docker Engine from binaries | Docker Docsで言及されているDockerエンジンのみのインストールをおこなう。

管理者権限でPowerShellを起動

Enable-WindowsOptionalFeature -Online -FeatureName $("Microsoft-Hyper-V", "Containers") -All

一度再起動して、管理者権限で再度PowerShellを起動

winget install --scope machine -ei --id Docker.DockerCLI
dockerd --register-service

なお、上述の手順でwingetでscopeをmachineに設定したり、サービスとして登録している都合、winget update --allでエラーが発生するため、その対象から除外しておく。 (アップデート手順は後述)

winget pin add --id Docker.DockerCLI

Windows Containerの起動

現在のユーザからdockerコマンドを使用できるようにするため、管理者権限のPowerShellで以下を実行

New-LocalGroup -Name 'docker-users' -Description 'Users of Docker for Windows'
Add-LocalGroupMember -Group 'docker-users' -Member "$([System.Security.Principal.WindowsIdentity]::GetCurrent().Name)"

C:\ProgramData\docker\config\daemon.jsonに以下のファイルを作成する。
※他の設定を変更するときは、このサイトを参照すること。

{
        "group" : "docker-users"
}

管理者権限のPowerShellで以下を実行し、dockerデーモンを起動する。

Start-Service docker

Windows Containerはプロセス分離、Hyper-Vの2つのモードがあり、プロセス分離はLinuxコンテナと同じようにカーネルを共有して動かすもの、Hyper-Vは仮想化により動かすものみたい。 Linuxとは異なり、カーネルとOSイメージが密接に結びついているようで、プロセス分離の場合はホストOSと合致するOSイメージしか使用できないそう。ホストOSと異なるOSを使いたい場合はHyper-Vを使うべし、ということらしい。

Windows 11 ProではデフォルトはHyper-V。プロセス分離で動かす場合は、コンテナ起動時に引数で明示する必要がある。

プロセス分離で起動する場合は、以下のようなコマンドになる。

docker run --isolation=process -d -t --name container-01 mcr.microsoft.com/windows/servercore:ltsc2022 cmd.exe

後は通常のdockerと同じような感じで使える(みたい)

docker exec -it container-01 powershell

GUIが使えないので、リモートのファイルサーバのマウントはnet use等、コマンドでどうにかする必要はあるが、それなりに使えそう。

ESETを使用している場合

ESETのSSL/TLSプロトコルフィルタリングの機能により、証明書の問題が発生する可能性がある。その場合は、ESETの証明書をホストでエクスポートし、それをコンテナでインポートする必要がある。

ESETの詳細設定画面を開き、下図の赤線部分(証明書の表示)をクリックする。

ファイルにコピーをクリック

証明書にエクスポートウィザードを進めて、証明書をファイルにエクスポートする。 エクスポートした証明書は、docker cpコマンドでコンテナにコピーする。

docker cp .\eset.cer container-01:C:/

コピーした証明書をコンテナでインポートする。

docker exec -it container-01 powershell -c "Import-Certificate -CertStoreLocation cert:\localMachine\Root C:/eset.cer"

Docker Composeを使用する場合

管理者権限でPowerShellを起動

winget install --scope machine -ei --id Docker.DockerCompose
winget pin add --id Docker.DockerCompose

docker-composeコマンドが使用できるようになる。(docker composeではない)

Dockerをアップデートする場合

上述の手順でDockerをインストールした場合、以下の手順でアップデートする。

管理者権限でPowerShellを起動

Stop-Service docker
winget update --scope machine -ei --id Docker.DockerCLI
winget update --scope machine -ei --id Docker.DockerCompose
Start-Service docker