ヤフオクで買ったサーバにWindows Server 2016のCOAラベルがついていたので、OS入れてdockerを入れました。

はじめに

ランタイムの選定

  1. containerd
  2. Moby
  3. Mirantis Container Runtime

今回はMobyを入れる

Windowsコンテナ機能の準備

  • Windowsコンテナにはプロセス分離とHyper-V分離がある
    • 分離モード | Microsoft Learn
    • プロセス分離
      • Linuxにおけるコンテナと同じ感じ。Windowsの中でWindowsコンテナが動く
      • カーネルはホスト側と共有する
      • WindowsServerだとデフォルト値はこっち
    • Hyper-V分離
      • Docker Desktopみたいな感じ。Hyper-Vの仮想マシンが作られて、その中でコンテナが動く
      • カーネルはホスト側と分離される
      • Windows上でLinuxコンテナを動かしたい場合はこっち
      • windows10にDocker Desktop入れた時はこっち
  • Docker Engineではプロセス分離しか動かない
# コンテナ機能の有効化
Install-Feature -FeatureName Containers
# プロセス分離だけでなくHyper-V分離も使いたい場合はHyper-Vも入れる。dockerはHyper-V分離対応していないので入れていない
#Install-Feature -FeatureName Hyper-V
# 再起動
Restart-Computer

# コンテナ用ネットワークの確認。今は何も無いはず
Get-ContainerNetwork

Dockerインストール

# インストールするDockerのバージョン番号。リリースページを見て適宜変更 https://download.docker.com/win/static/stable/x86_64/
$DockerVersion = "20.10.21"

# dockerバイナリのダウンロード
Invoke-WebRequest -Uri "https://download.docker.com/win/static/stable/x86_64/docker-$DockerVersion.zip" -OutFile "~/Downloads/docker-$DockerVersion.zip" -UseBasicParsing
# 展開。展開先はProgramFiles配下
Expand-Archive -Path "~/Downloads/docker-$DockerVersion.zip" -DestinationPath $Env:ProgramFiles

# Windowsサービスに登録
& "$Env:ProgramFiles/docker/dockerd.exe" --register-service
# サービス開始。自動起動設定になっているので次回からは不要
Start-Service -Name docker

# ネットワーク確認。natとnoneが出来てるはず
& "$Env:ProgramFiles/docker/docker.exe" network ls
# 内部的にHNSを叩いているっぽい?のでpowershellでもnatネットワークが見える
Get-ContainerNetwork

Docker Composeインストール

なにかと便利なDocker Composeも入れておく。必須ではない

# インストールするDocker Compose v2のバージョン番号。リリースページを見て適宜変更 https://github.com/docker/compose/releases
$DockerComposeVersion = "v2.14.2"

# docker-composeバイナリのダウンロード。直接実行せずブラグインとして使うのでcli-pluginsに入れる
[Net.ServicePointManager]::SecurityProtocol += [Net.SecurityProtocolType]::Tls12
Invoke-WebRequest -Uri "https://github.com/docker/compose/releases/download/$DockerComposeVersion/docker-compose-windows-x86_64.exe" -OutFile "$ENV:ProgramFiles/docker/cli-plugins/docker-compose.exe"

パスを通す

不便なのでパスを通す。必須ではない。

# dockerのパスを通す
$NewPath = [Environment]::GetEnvironmentVariable('PATH', 'Machine')
$NewPath = "$NewPath;$ENV:ProgramFiles\docker"
[Environment]::SetEnvironmentVariable('PATH' , $NewPath , 'Machine')
# パス反映のため一度ログオフ
logoff
# 確認。バージョンが出るはず
dockerd.exe -v
docker.exe version
# composeも読まれているはず
docker.exe compose version

コンテナ起動

ここから非常に遅い

  • WindowsServer2016なのでservercoreイメージぐらいしかなく、それを起動すると約6GBのダウンロードが走る。5分ぐらいかかる
  • その後、Extractingしているようで、SSDを積んでいてもさらに10分くらいかかる
  • 今回はservercoreを起動してみたが、より新しいServerOSを使っているならnanoserverの方がテストに向いているはず
# コンテナイメージをダウンロード
docker.exe image pull mcr.microsoft.com/windows/servercore:ltsc2016
# 起動してみる。pingが届くことを確認。--rmがついているのでコンテナは即削除される
docker.exe run --rm mcr.microsoft.com/windows/servercore:ltsc2016 ping 8.8.8.8
# -itをつけて対話的な操作もできる
docker.exe run -it --rm mcr.microsoft.com/windows/servercore:ltsc2016 powershell

これでdockerインストールは完了

(失敗) containerdインストール

以降、やってみたけど実用的ではなかった手順。悔しいので残す。

ネットワーク作成

  • コンテナが使う仮想ネットワークインタフェースを作る。ModeはTransparent
# どのネットワークアダプタを使うか決まっている場合はそれを取得
$netAdapter = Get-NetAdapter -Name LAN1
# 決まっていなければUPしているやつを取得
#$netAdapter = (Get-NetAdapter | Where-Object {($_.Status -eq 'Up') -and ($_.ConnectorPresent)})[0]
# Transparentネットワークを作る。なんでTransparentなのかは分からないが、スクリプトがそうなっているので従う
New-ContainerNetwork -Name "Transparent" -Mode Transparent -NetworkAdapterName $netAdapter.Name
  • 「ネットワークと共有センター」のNIC一覧とか見ると増えたのが分かる

下準備

# TLS1.2の一時有効化
[Net.ServicePointManager]::SecurityProtocol += [Net.SecurityProtocolType]::Tls12

tarインストール

# Visual C++パッケージダウンロードとインストール
Invoke-WebRequest -Uri https://aka.ms/vs/17/release/vc_redist.x64.exe -OutFile "~/Downloads/VC_redist.x64.exe" -UseBasicParsing
& "~/Downloads/VC_redist.x64.exe"

# インストールするlibarchiveのバージョン番号。リリースページを見て適宜変更 https://github.com/libarchive/libarchive/releases
$LibarchveVersion = "3.6.1"
# tarのダウンロードと展開。展開先はProgramFilesの配下
Invoke-WebRequest -Uri "https://github.com/libarchive/libarchive/releases/download/v$LibarchveVersion/libarchive-v$LibarchveVersion-amd64.zip" -OutFile "~/Downloads/libarchive-v$LibarchveVersion-amd64.zip" -UseBasicParsing
Expand-Archive -Path "~/Downloads/libarchive-v$LibarchveVersion-amd64.zip" -DestinationPath $ENV:ProgramFiles

containerdインストール

# インストールするcontainerdのバージョン番号。リリースページを見て適宜変更 https://github.com/containerd/containerd/releases
$ContainerDVersion = "1.6.10"
# ダウンロード
Invoke-WebRequest -Uri "https://github.com/containerd/containerd/releases/download/v$ContainerDVersion/containerd-$ContainerDVersion-windows-amd64.tar.gz" -OutFile "~/Downloads/containerd-$ContainerDVersion-windows-amd64.tar.gz" -UseBasicParsing
# 展開。展開先はProgramFiles配下。これはcontainerdのデフォルトconfigに書かれているので、変えない方がいい
New-Item "$ENV:ProgramFiles/containerd" -ItemType Directory
# 新し目のWindowsなら普通にtar.exeでいい
& "$ENV:ProgramFiles/libarchive/bin/bsdtar.exe" -xvf "$HOME/Downloads/containerd-$ContainerDVersion-windows-amd64.tar.gz" -C "$ENV:ProgramFiles/containerd"

CNIプラグインのインストール

# インストールするCNIのバージョン番号。リリースページを見て適宜変更 https://github.com/microsoft/windows-container-networking/releases
$WinCNIVersion = "0.3.0"
# ダウンロード
Invoke-WebRequest -Uri "https://github.com/microsoft/windows-container-networking/releases/download/v$WinCNIVersion/windows-container-networking-cni-amd64-v$WinCNIVersion.zip" -OutFile "~/Downloads/windows-container-networking-cni-amd64-v$WinCNIVersion.zip" -UseBasicParsing
# 展開。展開先はcontainerd/cni/bin配下。これもconfigに書かれていたはず
Expand-Archive -Path "~/Downloads/windows-container-networking-cni-amd64-v$WinCNIVersion.zip" -DestinationPath "$ENV:ProgramFiles/containerd/cni/bin"

nerdctlのインストール

# インストールするnerdctlのバージョン番号。リリースページを見て適宜変更 https://github.com/containerd/nerdctl/releases
$NerdCTLVersion = "1.0.0"
# ダウンロード
Invoke-WebRequest -Uri "https://github.com/containerd/nerdctl/releases/download/v$NerdCTLVersion/nerdctl-$NerdCTLVersion-windows-amd64.tar.gz" -OutFile "~/Downloads/nerdctl-$NerdCTLVersion-windows-amd64.tar.gz" -UseBasicParsing
# 展開。展開先はProgramFiles配下。どこでもいい気がする
New-Item "$ENV:ProgramFiles/nerdctl" -ItemType Directory
# 新し目のWindowsなら普通にtar.exeでいい
& "$ENV:ProgramFiles/libarchive/bin/bsdtar.exe" -xvf "$HOME/Downloads/nerdctl-$NerdCTLVersion-windows-amd64.tar.gz" -C "$ENV:ProgramFiles/nerdctl"

パスを通す

# containerdとnerdctlのパスを通す
$NewPath = [Environment]::GetEnvironmentVariable('PATH', 'Machine')
$NewPath = "$NewPath;$ENV:ProgramFiles\nerdctl;$ENV:ProgramFiles\containerd\bin"
[Environment]::SetEnvironmentVariable('PATH' , $NewPath , 'Machine')
# パス反映のため一度ログオフ
logoff
# 確認。ヘルプメッセージが出るはず
ctr.exe -h
containerd.exe -h
nerdctl.exe -h

containerd起動

# デフォルトconfigをファイルに出力。この中にファイルパスなどが書かれているため、どうしてもProgramFilesに置きたくない場合はここをいじる
containerd.exe config default | Out-File "$ENV:ProgramFiles/containerd/config.toml" -Encoding ascii
# Windowsサービスに登録
containerd.exe --register-service
# 開始
Start-Service -Name containerd
# 呼んでみる(何もないはず。エラーが出ないことだけ確認)
nerdctl.exe image ls --all

インストールスクリプトはここまで。ここから先は個人的に試したもの

コンテナ起動

# コンテナイメージをダウンロード。数GBのダウンロードが走り、さらに展開が行われる。落ちているように見えるが実は処理が進んでいるので、安易にctrl+cしてはいけない
nerdctl.exe pull mcr.microsoft.com/windows/servercore:ltsc2016
# 起動してみる。pingが起動したらOK。pingの送信は失敗するはず
nerdctl.exe run --rm mcr.microsoft.com/windows/servercore:ltsc2016 ping 8.8.8.8

ネットワークに繋がらないことに気づく。nerdctlではダメらしい。

さらに、ここで謎の事象が起きる

  • なぜかスタートメニューでピン留めしていたサーバーマネージャーのショートカットが消える
    • ServerManager.exe で起動するので気にしない
  • スタートメニューの「Windows管理ツール」と中身が英語になる
    • 理由は全く分からないが、使えない訳では無いので気にしない
  • 一度サインアウトすると、以降WindowsDefenderが起動しなくなるしコンテナイメージも壊れる
    • nerdctl image ls するとイメージが壊れていると表示される
    • さすがにWindowsDefender壊れるのは厳しい

もう何も分からないので諦める

おわりに

containerd何も分からない