Windows11 ProのHyper-VでUbuntu22 Desktop VMのDocker開発環境をサクっとつくる

## 目的：Hyper-Vを使ったUbuntu22 Desktop環境の準備

この記事の執筆時点で、Docker Desktopが有償となり、猶予期間の2022/01/31も越えてからもう半年は余裕で経過しています。私はこの記事を書くまで全く知らず、そもそもDocker Desktopを使わずにVirtualBox上のUbuntuマシン達でほとんどの仕事をこなしてきました。

https://www.docker.com/blog/updating-product-subscriptions/

ちょうど一年前のあたり、なんとかしたい人たちがたくさんいるのを、Twitterではよく眺めていました。そういった人たちはだいたいWSLを利用していたようですが、WSLから移行する類の話はさすがにまだありません。とはいえ、WSLに疲れ、普通にVMを立ててDocker Engineを運用し始めたかつての私のように、WSLから移行する方もいるかもしれません。

この記事では、Ubuntu22 Desktop上でDocker Engineを利用する手法に移行してもらえるような状況をどうやってつくっていくかを実際に記事にしていこうと思います。

この対応にはかなりの時間がかかるだろうと身構えていたのですが、実際のところは非常に簡単に準備が終わってしまいました。使用感としてはMacOSのParallelsと同じような感覚でほとんどすべての作業がおわってしまいます。

## この記事の前提条件
Windowsのお作法にしたがうえで、以下の前提条件をクリアできる方が対象になると思います。

### Windows標準機能のHyper-Vを使う
私はVirtualBoxからUbuntu22 Desktopを使ってきたのですが、これはMacbookがIntel CPUだった時代にほぼ環境を一致させたかったから、というところがあります。いまの私はM1チップのiMacを使い、Parallels上のUbuntuで簡単なPythonやC言語のUnix実験用コードを実行するくらいしか休日にはしておらず、これまで開発環境用に使っていたWindowsマシンも新調したのもあるので、いっそのことWindowsの標準機能でがんばってみようかな、と思って書いています。今のM1チップiMacだとAMD64の命令セットアーキテクチャなコンテナを素で動かすことができなくて何かと面倒という側面もあります。そのせいもあって結構コンテナをつかった開発を土日にやるのはずいぶんご無沙汰となります。

### Windows Pro版であること
Hyper-Vを利用するためにはPro版を利用する必要があります。なのでゲーミングノートなどを購入した場合のたいていは、MicroSoft StoreのページからPro版にアップグレードを行う必要があります。14000円ほどかかります。MacのParallelsの製品版が10000円ほどなので、それを買うような感じに近いです。今回はそうしてアップグレードしたWindows11 Proを使用していますが、Windows10 Proでも同等の実装は可能だと思います。

なお普段からDocker Desktopを利用されている方の場合は、すでにVMをHyper-Vで動かす仕様になっていてオンになっているはずなので、特に気にする必要はないかもしれません。

### WSLを運用しない理由
これは私がWSL2をほぼ利用してないので、WSL1とWSL2になりたてのマシンを使っていた過去の話になってしまうのですが、CLI上でWindowsのOSのインターフェースとUnixのカーネルのインターフェースがごたまぜになって使わないといけなかった記憶があるからです。特にネットワークがらみとファイルがらみなのですが、WindowsとUnixだと考え方がかなり違い、コマンドラインも別個で打つ必要がありました。結局WSL2もVMとして動かしているのが実態だからです。PowerShellと完全互換ができればよかったのですが、Windows OSの全体像も、Windows APIもそう簡単に変えられるものではないこともインサイドWindows上下巻を読んだ今は重々承知しています。

それならいっそのこと、OSとしては完全に分けて運用してしまい、ファイル連携は基本的にWebシステムなどの別の手法で連携してしまうほうがいまは直感的に使えそうな気がしています。

### 注意：Hyper-V有効化まではPowerShellを2回だけ使用
公式ドキュメントに準拠した操作をした都合上、Hyper-V有効化まではPowerShellを2回だけ使用しました。とはいえたいして使わないので不慣れな方でもご安心ください。

私も正直PowerShellなどはよくわかりませんが、以下の記事を読んでいるとそこそこUnixShellとの違いを理解して今後使いやすくなるかもしれません。

PowerShellで簡単にWindowsリソース系を確認するコマンドの一覧とUnixShellとの違い:

https://qiita.com/GCkurabe/items/bee58c6302f8bf7b73f7


## Hyper-Vを有効化する
早速、以下のMicrosoft公式ドキュメントを参考に実施します。

Windows 10 上に Hyper-V をインストールする：

https://learn.microsoft.com/ja-JP/virtualization/hyper-v-on-windows/quick-start/enable-hyper-v


以下のコマンドを管理者権限で実行します。このあと再起動を行うか否かの出力が出るのでYを押して再起動します。

```
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All
```

再起動完了後に以下のコマンドを管理者権限で実行します。DISMという展開イメージのサービスと管理のツールというものを入れます。これが具体的にどういう動作をしているのかはいまのところよくわかりません......なんだろうこれ......

```
DISM /Online /Enable-Feature /All /FeatureName:Microsoft-Hyper-V
```

## 仮想マシンの作成

以下のマイクロソフト公式ドキュメントを利用します。

Windows 10 Creators Update で Hyper-V を使用して仮想マシンを作成する:

https://learn.microsoft.com/ja-JP/virtualization/hyper-v-on-windows/quick-start/quick-create-virtual-machine


まず公式ドキュメントに従い以下のようにGUI上から操作を行っていきます。

```
スタート メニューから [Hyper-V クイック作成] を開きます。
```

すると早速オペレーティングシステムの選択画面が表示されるのでUbuntu 22.04LTSを選択して仮想マシンの作成を押します。MacOSのparallels並みに楽でいいですね。VirtualBoxやESXiの場合は別途isoファイルを用意してインストール作業が必要になります。ではこれで作成するまで少し待ちます。

その後「仮想マシンが正常に作成されました」と表示されるので、「接続」を押します。そして「起動」を押します。するとすぐさまUbuntuの画面が表示されました。

あとは任意のユーザー設定を注入することでUbunutu 22 Desktopの作成は完了です。

あとこのUbuntu 22のVMは、これといったインストール作業をせずともVMとHyper-V親機であるWindowsのマシンとでテキストのコピペが連動するようになっています。これはRDPっぽいものを使用していることによるものなんでしょうが、非常に使いやすくて便利です。ほとんどの人が言及していないのが不思議なくらい操作が簡潔にできています。

## Docker Engineインストールと各種設定

ここからはUbuntu Desktop上に切り替えて作業を行います。以下の公式ドキュメントを参考に勧めますが、やることは単純です。docker.shというスクリプトを実行するだけでDocker Engineが入ってしまいます。本番環境では様々なパッケージ管理の変更がかかるリスクがあるため一般的におすすめできませんが、今回のようにできたての開発用VMであれば問題はないと思います。

Install Docker Engine on Ubuntu:

https://docs.docker.com/engine/install/ubuntu/

ただこのマシンにはcurlがデフォルトで入っていないので以下のコマンドでパッケージ関連の情報を最新化したあとcurlのインストールをしておきます。

```
sudo apt update
sudo apt install curl
```

この状態でcurlを実行し、手に入れたget-docker.shを実行します。

```
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
```

すると以下のようにDocker Engineが導入できました。

```
+ sh -c docker version
Client: Docker Engine - Community
 Version:           20.10.20
 API version:       1.41
 Go version:        go1.18.7
 Git commit:        9fdeb9c
 Built:             Tue Oct 18 18:20:18 2022
 OS/Arch:           linux/amd64
 Context:           default
 Experimental:      true

Server: Docker Engine - Community
 Engine:
  Version:          20.10.20
  API version:      1.41 (minimum version 1.12)
  Go version:       go1.18.7
  Git commit:       03df974
  Built:            Tue Oct 18 18:18:08 2022
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.6.8
  GitCommit:        9cd3357b7fd7218e4aec3eae239db1f68a5a6ec6
 runc:
  Version:          1.1.4
  GitCommit:        v1.1.4-0-g5fd4c4d
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0
```

実際にDocker Engineが動作するか確認します。以下のようにsudoしてhello-worldコンテナを実行してうまくいけば問題ないでしょう。

```
sudo docker run hello-world
[中略]
Hello from Docker!
```

とはいえデフォルトで管理者であるrootがオフになっているUbuntuで通常ユーザーでコンテナのためにsudoをし続けるのはそこそこに億劫なので、開発環境に限り、以下のようにdockerをsudoなしで実行可能にしていきます。

まずはdockerというgroupを追加します。

```
sudo groupadd docker
```

次にdockerグループに作成したユーザーを追加します。

```
sudo usermod -aG docker $USER
```

これで端末が完全に閉じられて開きなおせれば設定の読み込みが行われて反映されるのですが、RDPで無理やりつないでいるのもあるので手っ取り早くVM自体を再起動してしまいます。

なお再起動後にHyper-V側での接続に一回確実に失敗するので再接続すると、VNCっぽい画面がでてくるのですがこちらは特に気にせずユーザー名とパスワードを入力することで入ることができます。

その後以下のようにsudoなしでhello-worldを実行できれば完了です。

```
docker run hello-world
```

あと再起動してすぐこのコマンドが打てたことでお気づきになられた方もいるかもしれませんが、dockerがすでに起動時に起き上がってくるようになっています。昔はこれらを手動で設定する必要があったのですが、Ubuntuの場合は自動で設定してくれるようです。いい時代になりましたね。

## おわりに

これでDockerの開発環境はHyper-Vベースで整いました。時代が進んでものすごく簡単にできるようになっていて感動的です。私はこのマシンを使ってDockerコンテナいじりにいそしんだりしようと思います。