tech.guitarrapc.cóm

Technical updates

Windows開発環境をscoopで継続的に構築する

以前 Windows の開発環境を scoop で構築しているということを書きました。

tech.guitarrapc.com

その際に、scoopを継続的に使っていくためのツール ScoopPlaybook を書いたことに触れました。 今回はその ScoopPlaybook の紹介です。

目次

TL;DR

  • ScoopPlaybook という PowerShellモジュールを作った(2年近く使っている)
  • scoop で何をインストールするかをYAML定義して使える
  • Scoop-Playbook コマンドでYAML通りに実行される
  • 使い心地は、Ansible Playbook のYAML定義とコマンドにインスパイアされている

scoop 使っていて、YAMLでインストールするツールを定義したい方は使ってみてください。

目指す姿

私は普段からOS環境を壊すことをアリと考えています。 ただし壊すからには再構築にコストをなるべくかけたくないため、対象のマシン上で再構築がコマンド1つでできるようにしています。 macOS は Homebrew や defaultsをAnsible Playbookで構築し、Ubuntu は Ansible Playbook で構築しています。

Ansible Playbook を使うことで、ほどよく緩くいい感じの目指す姿が可能になります。

  • 利用する開発ツールをYAMLに定義して
  • 何度実行しても同じ結果に収束させる

例えば Homebrew でインストールする場合は次のように定義できます。

# roles/homebrew/tasks/main.yaml
- name: 'homebrew packages installation'
  homebrew:
    name: '{{ item.name }}'
    state: "{{ item.state|default('present') }}"
  with_items: "{{ homebrew_packages }}"

# roles/homebrew/vars/main.yaml
homebrew_packages:
  - name: autoconf
  - name: awscli
  - name: aws-iam-authenticator
  - name: azure-cli
  # and so on....

一度定義してしまえばツールを定義に追加したり、アンインストール ( state: "absent" ) を指定するだけとメンテナンスが非常に簡単です。

site.yml を置いたルートパスでいつも同じコマンドを実行するだけで、YAML定義通りに環境が構築されます、便利。

$ ansible-playbook -i hosts site.yml

sudo が必要な操作 (become) なら、実行時に入れるだけです。

ansible-playbook -i hosts site.yml --ask-become-pass

WSL との相性もよく、気軽に環境を壊してサクッと作り直すことがコストでなくなります。

自分の環境にどんなツールをいれているかを説明することがふとしたときにあるのですが、定義によって、いつでも確認したり継続的に変更をかけたり、場合によっては他人に共有できるのは個人的に好みです。

WindowsでAnsiblePlaybook のようなアプリケーションインストール基盤を作る

環境の再構築はWindowsでもたびたび行います。(OSいれなおしでなくてもリセットはやりますよね)

scoopを使っていくことに決めたときに、コマンドの羅列地獄になるのは嫌だと思いました。 しかしAnsible をWindows localhost に実行はサポートされていないので、Ansible Playbook のような定義とインストールを提供することにしました。(WSLからAnsible実行するというのはナシ派) その晩にザクっと書いたのが ScoopPlaybook という PowerShell Module です。

github.com

あんまり使い方とか書いていないので、どういう利用をするのか紹介します。

scoop の通常のインストール

例えば、scoop でgow、jq、time、unzipをインストールする場合、コマンドラインで次のように実行するでしょう。

scoop install gow jq time unzip

あるいは、次のようにコマンドを分けているかもしれません。

scoop install gow
scoop install jq
scoop install time
scoop install unzip

アンインストールもコマンドラインで制御できます。

scoop uninstall gow

入っているツールは scoop list で見えますが、ほかの環境や再構築、追加インストールをするときはいちいち考えるの嫌になります。

ScoopPlaybook で定義からインストールする

ScoopPlaybook はAnsible Playbook でやっていたのと同じ目指す姿を提供します。

  • 利用する開発ツールをYAMLに定義して
  • 何度実行しても同じ結果に収束させる

利用方法は Ansible Playbookに合わせています。

  • ルートパス/site.ymlに 利用する role のYAML定義し、
  • ルートパス/roles/バケット/tasks/main.yml にツールをYAML定義したら、
  • ルートパスで、Scoop-Playbook コマンドを実行すると、Scoopバケットやツールが定義通りにインストール/アンインストールされる

YAMLで定義して、コマンド1つで定義を実行。ただそれだけです。 実際にどうやるのかイメージしにくいので利用例を見てみましょう。

利用例

先ほどのmainバケットのツールをScoopPlaybookでYAML定義してインストールしてみましょう。 ScoopPlaybook モジュールとYAM解析モジュールをインストールします。PowerShell 5.1 以降で動作します。

PS> Install-Module ScoopPlaybook -Scope CurrentUser
PS> Install-Module "PowerShell-Yaml" -Scope CurrentUser

適当にルートパスを切ります。

md ./begin
cd ./begin

まずは、インストールしたいアプリの定義YAMLを ルートパス/roles/main/tasks/main.yml に定義します。

PS> mkdir roles/main/tasks
PS> New-Item roles/main/tasks/main.yml
PS> vim roles/main/tasks/main.yml
- name: "Install main tools"
  scoop_install:
    state: present
    bucket: main
    name:
      - gow
      - jq
      - time
      - unzip

インストールするロールを指定したYAML定義 site.yml をルートパスにおきます。

PS> New-Item site.yml
PS> vim site.yml

今回のロールは main なのでこれを1つ指定します。

name: Windows Setup
roles:
  - main

早速定義をドライランしてみましょう、次のコマンドを site.yml のパスで実行します。

PS> Scoop-Playbook -Mode check

scoop のバケットを更新して (scoop update) 、ツールがインストールされるか実行計画を確認できます。

PRE [scoop : status] ***************************************************************
  [o] skip: [run with 'check' mode]
  [o] skip: [prerequisiting availability]
  [o] skip: [updating buckets]
  [o] check: [scoop-update: Updating Scoop...]
  [o] check: [scoop-update: Updating 'main' bucket...]
  [o] check: [scoop-update: Scoop was updated successfully!]
  [o] skip: [status checking]
  [o] skip: [scoop-status: Scoop is up to date.]
  [o] check: [scoop-status: Updates are available for:]
.... 省略
PLAY [Windows Setup] ***************************************************************

TASK [main : Install main tools] ***************************************************
  [!] check: [scoop_install: gow] => Installed: No
  [!] check: [scoop_install: jq] => Installed: No
  [!] check: [scoop_install: time] => Installed: No
  [!] check: [scoop_install: unzip] => Installed: No

問題なければインストールします。Mode パラメーターを省略するか、-Mode run を明示的に付けると実行します。

PS> Scoop-Playbook
PRE [scoop : status] ***************************************************************
.... 省略
PLAY [Windows Setup] ***************************************************************

TASK [main : Install main tools] ***************************************************
  [!] changed: [scoop_install: gow] => Installed: No
  Installing 'gow' (0.8.0) [64bit]
Loading Gow-0.8.0.exe from cache
Checking hash of Gow-0.8.0.exe ... ok.
Extracting dl.7z ... done.
Running pre-install script...
Linking ~\scoop\apps\gow\current => ~\scoop\apps\gow\0.8.0
.... 省略
'gow' (0.8.0) was installed successfully!
  [!] changed: [scoop_install: jq] => Installed: No
  Installing 'jq' (1.6) [64bit]
.... 省略
'jq' (1.6) was installed successfully!
  [!] changed: [scoop_install: time] => Installed: No
  Installing 'time' (0.2018.07.25) [64bit]
.... 省略
  [!] changed: [scoop_install: time] => Installed: No
  Installing 'time' (0.2018.07.25) [64bit]
.... 省略
'time' (0.2018.07.25) was installed successfully!
Notes
-----
Please use 'timecmd' instead of 'time' in cmd.exe.
  [!] changed: [scoop_install: unzip] => Installed: No
  Installing 'unzip' (6.00) [64bit]
.... 省略
'unzip' (6.00) was installed successfully!

再度実行しても同じ結果に収束します。 もし更新があれば更新してくれます。

PS> Scoop-Playbook
Scoop-Playbook
PRE [scoop : status] ***************************************************************
.... 省略
PLAY [Windows Setup] ***************************************************************

TASK [main : Install main tools] ***************************************************
  [o] skip: [scoop_install: gow] =>   gow  0.8.0
  [o] skip: [scoop_install: jq] =>   jq  1.6
  [o] skip: [scoop_install: time] =>   time  0.2018.07.25
  [o] skip: [scoop_install: unzip] =>   unzip  6.00

何かの理由でscoop コマンドで直接インストールすることもあるでしょう、そんな時は定義に一行足せばいいだけです。 もし scoop コマンドで誤ってアンインストールしても、Scoop-Playbook を実行すれば元通りです。

Scoop で管理したいツールを定義通りに実行する。それができます。

普段の利用例

私は ScoopPlaybook を使ってYAML定義をして GitHub においています。 参考に私が普段使っているリポジトリを置いておきます。ルートパスはこのリポジトリの ./envs/windows/ パスです。

local-provisioner/envs/windows at main · guitarrapc/local-provisioner · GitHub

そのため、環境構築するときは次のコマンドを実行しています。

git clone https://github.com/guitarrapc/local-provisioner.git
cd local-provisioner/envs/windows
. ./prerequisites.ps1
sudo Scoop-Playbook

ツールの追加や削除をしたいときは、定義のYAML を修正して git commit/push するだけです。 バッチファイルやスクリプトではないので、どのように動作するかは考えず、ツールをYAMLに並べるだけなのはメンテの面で作ってよかったと思っています。 実際これなしで scoop とかいやです。

できること

ScoopPlaybookは次の操作が可能です。これしかできないです。

  • scoop_bucket_install: バケットの追加、削除
  • scoop_install: ツールのインストール、アンインストール

バケットの追加、削除

scoop は任意のGitHubリポジトリなどをバケットにできます。scoop bucket add xxxx ScoopPlaybook も scoop_bucket_install でバケットの追加、削除をサポートしています。

例えば extras バケットを追加する場合、次のように書けます。

- name: "Install extras bucket"
  scoop_bucket_install:
    state: present
    bucket: extras

extras バケットは特別扱いされていますが、自分の GitHub URL を指定したい場合は次のようになります。

- name: "Install guitarrapc bucket"
  scoop_bucket_install:
    state: present
    bucket: guitarrapc
    source: https://github.com/guitarrapc/scoop-bucket.git

もしも追加したバケットを消したいならstate に absent を指定します。 (source は省略できます)

- name: "Uninstall guitarrapc bucket"
  scoop_bucket_install:
    state: absent
    bucket: guitarrapc

それぞれのキーは、scoop bucket コマンドに合わせてあります。

  • state: present か absent を指定
  • bucket: 対象のバケット名を指定
  • source: GitHub などのバケットURLを指定

ツールのインストール、アンインストール

scoop はバケットからツールのインストール、アンインストールができます。scoop install xxxx ScoopPlaybook も scoop_install でツールのインストール、アンインストールをサポートしています。

- name: "Install main tools"
  scoop_install:
    state: present
    bucket: main
    name:
      - gow

先ほど追加した gow をアンインストールするなら次のように書けます。

- name: "Uninstall main tools"
  scoop_install:
    state: absent
    bucket: main
    name:
      - gow

それぞれのキーは、scoop install コマンドに合わせてあります。

  • state: present か absent を指定
  • bucket: 対象のバケット名を指定
  • name: ツールを配列で指定

すでにインストールされているツールに更新がある場合は、Scoop-Playbook 実行時に更新してくれます。便利。

管理者権限で実行したい

scoop はユーザー権限が基本でーとか言いますが、ツールによってはFiddler のように管理者権限がないとインストールできないものもあります。 そんなときは sudo コマンドです。

sudo コマンドをインストールしておいて(scoop install sudo 相当)

- name: "Install main tools"
  scoop_install:
    state: present
    bucket: main
    name:
      - sudo

Scoop-Playbook を sudo つきで実行すればok です。

sudo Scoop-Playbook

まとめ

一人で使ってて満足していたんですが、WinGet が出てきて未来はどうなるかと楽しみにしています。 ただ、WinGet はこのままいくとこういう YAML 定義に関しては手を出さず、誰かが何か作るのでしょう。

アンインストールやUAC考慮がない、今のWinGet 触る気はありませんが、WinGetを触る将来が来たらこういうツール書くかもしれません。 ただ、その時はたぶん PowerShell では書かない気がするかもしれない。

WSL1 から WSL2 の対応

WSL1 を長い間使っていましたが、先日 Windows 10 Version2004 がリリースされて WSL2 に切り替えを行いました。

WSL2 いいのですが、WSL1 と同じように、あるいはちょっと欲張ろうと思うと少し困ったのでメモ。

目次

TL;DR

Windows 10 May 2020 Updateがリリースされてから2週間使ってますが、もう WSL1 に戻る気はないぐらいには気に入っています。おすすめです。 具体的には、

  • 👍: WSL2 にして apt/pip3 が爆速になってうれしい
  • 👍: WSL1 とおおむね使い勝手は変わらず、WSL2上のdockerでボリュームマウントが可能になってよかった(標準的なLinuxとみなせるようになった)
  • 🙅: WSL2 の Windowsボリュームのアクセスはとても遅くなった
  • 🙅: Windows のシステムボリュームは余計に食うようになったので 50GB 程度空きは欲しい (あるいはOSリセットすると減るはず)

kubernetes 周りに関しては、特段変化を感じません。

WSL1 で何をしていたのか

WSL1 では、Ubuntu 18.04 を動かして、中でアプリケーションやインフラにかかわるツールを動作させていました。 Docker でもいいのですが、普段使いのツールや、Windows でマウントしているファイルを(EOLを含めて) そのまま Linux で動作させたときの動作もサクッと確認できるのがいいのです。

  • dotnet core SDK
  • golang
  • cmake
  • Kubernetes (kubctl/helm/kubesec/sops...)
  • terraform
  • docker/docker-compose
  • aws cli/azure cli
  • jq/yq
  • sed 他

docker とWSL の使い分けはそのカジュアルさです。 WSLは、bash と入力するだけでほぼ Linux とみなせるインタラクティブな環境に行けるので、普段使いのUbuntu 環境に利用しています。多少無茶な使い方をしても、アンインストールして store から入れなおせばフレッシュになるので壊せる開発環境という感じです。 一方のdocker は、アプリ動作環境を閉じ込めるためや、特定のソフトウェアの挙動、壊れるだろうという操作やシステム設定の変更など戻すことがめんどくさいことをするときに使っています。

WSL2 で何をするのか

基本的な利用目的は変わりません。手軽にさくっと Linux 環境として Ubuntu を利用します。 WSL1 から WSL2 に変化することで期待したのは、ディスクIOです。 概ね事前にやっていた結果と Windows 10 Version 2004 における WSL2 に違いはなく、WSL1 に比べて ext4 上でのディスク書き込みの速度が上がりました。 具体的な変化は次の通りです。

  • apt update|instal が爆速になる
  • pip3 も爆速化
  • Windows マウントファイルへのアクセスは非常に低速に
  • WSL2上のDockerでボリュームマウントが可能になった

ディスクアクセスの改善は顕著です。具体的なシチュエーションだと、apt update/install に関しては、これまでUbuntu 18.04 を入れた後に実行すると10min 程度食うのを覚悟していたものが1min 程度になっています。pip3 も同様です、ansible 入れてみてください。 ただ、Windows のマウントディレクトリ ( /mnt/c など) でのファイル操作はけた違いに遅くなりました。(知ってた) そのため、例えばdocker-compose で Windows のフォルダを WSL2 からマウントするのはものを選びます。100MB を超えるdocker転送は永遠に終わらない気分になります。(node_modules とかつらい)

Windows のパス上からそのまま bash で WSL2 を起動する流れは変わらないものの、大き目なファイルサイズを伴う docker-compose に関しては Windows上で扱うか、ext4 上に git clone するのがいいでしょう。

しれっと書きましたが、WSL2ではWSL上のファイルをWSLのdockerにボリュームマウントできるようになっています。WSL1 では、WSL 上のファイルを WSL上で実行した docker にボリュームマウントできず、ふとしたdocker操作で挙動が違って無駄に時間を費やすことがありましたがなくなりました。最高です。

WSL2 への対応

WSL1 の環境を WSL2 にするにあたり、どのような対応をしたかメモしておきます。

Windows システムボリュームの利用が増えた

WSL1からWSL2にすると、Docker Desktop (35GB)、wsl (9GB)、Ubuntu 18.04(5GB) で 約50GB余計にシステムボリューム(C:) を利用するようになってしまいました。

デスクトップは長い間 256GB M.2 SSD (Samsung SSD 950 Pro) でやっていましたが、WSL2 にして残り 1.8MB になったためシステムボリュームを 1TB NVMe に差し替えました。 Crucial は 最近P2 が出ましたが、ちょっと試してみたかった P1 で。

https://www.crucial.jp/catalog/ssd/p1www.crucial.jp

なお、Windows.old を含めてゴミを消しても容量はすぐに埋まりきりがなくなったので仕方ない。

qiita.com

なお、Windows 10も入れなおして開発環境、WSL2を組みなおしたところ利用容量が 76.1GB になったので、まぁそんなものです。知ってた。(だから 256GB で過ごせていた) Windowsの入れ直しは、Media Creation Tool で Windows 10 May 2020 Update で USBブートを作るのが今も安定でした。

Windows Features が不要に

幸いなことに、 Docker Desktop for Windows をインストールすると WSL2 周りは一通り入ります。(Kernel のぞく) そのため、これまで Enable-WindowsOptionalFeature でインストールしていた Microsoft-Windows-Subsystem-Linux、Hyper-V は不要になりました。

https://github.com/guitarrapc/local-provisioner/compare/wsl1...604c08d7313060c681fc2ecb91d9839df7056ccf#diff-500458443dc2514ec7bec4fde7ce776eL1-L25

脱Hyper-Vは、Windows 10 Home でも利用できるようになっていますし最高ですね。(Virtual Box とかも動くし)

tech.guitarrapc.com

WSL OS

WSL2 でも、現状は Ubuntu 18.04 を使っています。 折を見て Ubuntu 20.04 に切り替えていきますが、まずは変化を見たいので変えていません。

Provisioning

WSL1 と変わらず、WSL2 においても ansible を使って環境を構築しています。 私の場合は、Windows / macOS / Ubuntu を各種環境を利用するので、全環境に対してこのリポジトリの内容を当てています。

github.com

Ubuntu 18.04 においては、WSL1/WSL2であっても ansible で当てています。 Diff は次の通りです。

https://github.com/guitarrapc/local-provisioner/compare/wsl1...724dad71fd0852173e10fbca4a961eec92db2710

いくつか初期化回りの変更をメモしておきます。

dockerの入れ直しをやめた

docker は、WSL1 においては docker.io の公式同様に入れなおしていましたが、WSL2 においてはデフォルトから変更していません。

-    - { role: "docker", tags: [docker] }
+    #- { role: "docker", tags: [docker] }

https://github.com/guitarrapc/local-provisioner/compare/wsl1...604c08d7313060c681fc2ecb91d9839df7056ccf#diff-b905abb381284c6c36b4ac2b6dc30641L24-L25

また、bashログイン時の起動も止めています。

- sudo -S cgroupfs-mount
- sudo usermod -aG docker $USER
- sudo service docker start
- # wsl1 using windows docker-compose. wsl2 don't need this line.
- # export DOCKER_HOST=tcp://localhost:2375 

https://github.com/guitarrapc/dotfiles-linux/commit/db47ddf5c1ba8400acb502b256c8a03bbcb5749b

WSL2でdocker の入れ直しをやめたのは、docker の入れ直しを行うことで Windows 上の Docker for Windows のイメージと WSL2 上のイメージ一覧が同期されなくなったためです。(Windows はWindows、WSL2 の UbuntuはUbuntu と個別にイメージを持つようになってしまった。)

# この結果を Windows と WSL で共有する
docker image ls

WSL2 を使うにあたって、Windows の状況がそのまま利用できるメリットを手放す理由は相応のものがない限り薄く、特に docker に関しては同じイメージが使えるのが最高なのでdocker の入れ直しはやめました。

systemd/snap

当初wsl2 なら snapも行けるしと思って試していた形跡があります。が、結局 snap使っていません。(また使えるようにファイルは残しています) 実際 systemd/snapd を動かして、snap 経由でのインストールも可能になりましたが、以下の理由で辞めています。

  • kubectl は意図通り snap のほうが楽だった
  • snap で差し替えたかった pip3 の snap ファイルが欲しいものではなかった
    • 具体的には ansible が公式がなく個人のパッケージは python2 版
  • Windows から bash や wsl で WSL2 を起動したときに、$HOME に移動するようになってしまう
    • WSL2 は、wsl や bash で Ubuntu に入ると Windows のパスのまま維持しますが、snap 対応を入れたスクリプトでのログインしなおしでパスが $HOME になってしまう

snapを使うことでバージョニングを楽にインストールをしたいと思ったのですが、なかなか難しいようです。 現状あんまり snap に頑張る気もないので、やめました、はい。

Windows パスの分離

WSL2 は WSL1 同様に、標準では Windows のPATH が $PATH に入ってきます。 これにより、WSL2 上で code . とすることで Remote WSL がVS Code で使えたりします。(~/docker.cfg も Windows の docker cred のパスが入っています)

Windows PATHがWSLで使えるのはすごく便利なのですが、WSL1 で Windows のパスとWSLのパスが競合してWSLでアプリ動作がおかしくなった経験があります。 そのため、 /etc/wsl.conf でPATH を停止しています。

[interop]
appendWindowsPath = False

wsl.conf をおいて、 wsl --shutdown を実行することでWSL上で Windows のパスが入らなくなります。

$ echo $PATH
/home/guitarrapc/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/home/guitarrapc/.dotnet/tools

まとめ

おおむねWSL2 にして幸せになります。 ディスク容量は明らかに食うようになるので、私は割り切ってシステムボリュームを1TB まで増やしてわずらわしさを感じないようにしました。 ただ、ラップトップでなくても、PCのシステムドライブはそれほど大きくないことも多いので要注意な感じがあります。

Windows 10 Home を Windows 2019 Server on Azure で Nested Hyper-V にインストールする

Windows 10 Home の WSL2 + Docker を検証するための環境を考えた時、Windows 10 Pro の Hyper-V にいれるのが手っ取り早いのですが、CPU仮想化支援の有効化コマンドレットに気づかず Windows Server 2019 上の Windows 10 Home じゃないとダメだっけと思ってさまよった時のメモ。

結果は VMのCPU仮想化支援を有効にすればどちらも変わらず動作する。

前の記事の前段となる個人的なメモです。ローカル環境が Windows 10 Home の人が環境を汚さずやるにはいいのでは。

tech.guitarrapc.com

目次

[:contens]

TL;DR

  • Windows 10 Home を Nested Hyper-V で動かす
  • Windows 10 Home on Hyper-V と変わらなず wsl2 + Docker Edge は動作する (Hyper-V の Windows 10 Home VMのの CPU 仮想化支援を有効にしよう)
  • Insiderビルドが長すぎるのでWindows 2004、あらためWindows 10 May 2020 Update はよ、ふたたび

前提

  • Dv3 or Ev3 が必要

Azure Virtual Machines で入れ子になった仮想化を有効にする方法 | Microsoft Docs

VMの構成

久々に terraform を使わず Azure Portal を確認してみます。 いつの間にか スポットインスタンスができるようになってて感動した。

適当に Resource Group を作っておきます。

  • Windows Server Gen2 Preview のイメージで Windows Server 2019 とする
  • Spot Instance
  • D4s_v3
  • Standard SSD

全部できるとリソースこんな感じ。

Nested Hyper-V の準備

Install-WindowsFeature -Name Hyper-V -IncludeManagementTools -Restart

再起動後に VM Swtich の構成

New-VMSwitch -Name "InternalNAT" -SwitchType Internal
$ifIndex = (Get-NetAdapter |where Name -match InternalNAT).ifIndex
New-NetIPAddress -IPAddress 192.168.0.1 -PrefixLength 24 -InterfaceIndex $ifIndex

NAT Network の構成

New-NetNat -Name "InternalNat" -InternalIPInterfaceAddressPrefix 192.168.0.0/24

Hyper-V を開いてVMの構築。この時Network は Internal NAT を向ける

Hyper-V はサクッと。NAT 指定だけ忘れずに

Windows 10 Home ISO を用意

MediaCreationTool1909 を入れる。IE がアレなので curl で落とす。

https://www.microsoft.com/ja-jp/software-download/windows10

curl -L  https://go.microsoft.com/fwlink/?LinkId=691209 -o MediaCreationTool1909.exe

ISO を設定

Boot Order を修正して ISO 起動できるようにする

あとは Windows 10 Home を入れる。

DHCP Server を Azure VM に用意

Azure VM 上の Nested Hyper-V ということは DHCP ないので、適当に Windows Server 2019 から DHCPを Internal NAT に配布します。

Install-WindowsFeature -Name DHCP -IncludeManagementTools

DHCP ツールを起動して、IPv4に新規スコープを追加し、 192.168.0.100-200/24 を設定

デフォルトゲートウェイに InternalNAT の 192.168,0.1 を指定

これで Hyper-V の VM を起動したり、ネットワークアダプターの無効/有効でIPが取得される。

残り

Windows 10 Home on Hyper-V (Windows 10 Pro) と同じ。

tech.guitarrapc.com

用が済んだら Resource Group ごとぐっぱい。Terraform 以外で作るの久々で相変わらずめんどくさかった。

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

Windows 10 Home の WSL2 + Docker を検証するための環境を考えた時、Windows 10 Pro の Hyper-V にいれるのが手っ取り早いのですが久々に Hyper-V 触ったので改めてメモ。

前の記事の前段となる個人的なメモです。ほしい内容は自分で書くしかない。

tech.guitarrapc.com

目次

[:contens]

TL;DR

  • Windows 10 Home を Hyper-V で動かす
  • Windows 10 Home on Hyper-V でも wsl2 + Docker Edge は動作する (Hyper-V の Windows 10 Home VMのの CPU 仮想化支援を有効にしよう)
  • Insiderビルドが長すぎるのでWindows 2004、あらためWindows 10 May 2020 Update はよ

Windows 10 のISO を入手する

Media Creation Tool で Windows 10 の ISO を生成する。

Windows 10 のダウンロード

2020/4/17 時点では、Windows10 1909 の生成ができる。

この記事では最新のMediaCreationTool1909 を用います

Hyper-V でマウントするためISO を作る

Single Language Windows でISOが作成されるので、Language を選んでおく。 今回は English (United Kingdom)

日本語でもなんでもお好きに

これでISOが生成される。

Windows 10 を Hyper-V にインストール

Hyper-V で新規VM を作成する

この辺りはコマンドでもいいけど GUI でいいや気分

先ほどのISO を指定して起動する

Local Installation source から Change Install source で ISO を指定

VM名を付けて生成したら起動する。

Windows 10 Home を選ぶ

ライセンスを入れる。

ここでライセンスを入れないとエラーになるので注意。

ライセンスを skip しようとするとエラー

Custom でインストールする。

Upgrade でも Custom でもどちらでもいい

Custom だとパーティションが設定できるけど Hyper-V なのでどうでもよし

インストールが実行される

何度か再起動がかかる

起動してきたら Region を選択

Keyboard を選択

Second Keyboard は不要なので skip

起動を待つ

再起動が走り、ユーザー選択になる。

Local User でのセットアップはできず、起動後に削除しろと言われる。

ローカルユーザーを作成するには、ネットワークを切って新規でユーザーを作ろうとすることで作成できる。(分かりにくい)

まずネットワークを切ろう。

VM の Settings から Network Adator を開く

Virtual switch を Not Connected に変更する。

Create account から ユーザーを適当に作ろうとすると Womething went wrong となる。

ここで Skip を選択すると ローカルアカウントで作成できる。

Insider Preview でどのみち Microsoft アカウントが必須なのでローカルアカウントの意味は薄い

あとはセットアップをしていく

これで起動する。

起動後の設定

  • ネットワークを戻す
  • Language で日本語を入れておく
  • システムロケールの日本語設定とUTF8化
  • Image の Checkpoint を作っておく
  • ホストマシンからVMのCPU 仮想化支援機能を有効にする

ネットワークを戻す

日本語を入れる

OSは英語だけど日本語ほしい人はストアからどうぞ

表示を日本語に切り替える

サインアウトして完了

システムロケールの日本語設定とUTF8化

Hyper-V Image の Checkpoint を作る

後でやり直せるようにしておく。

ホストマシンからVMのCPU 仮想化支援機能を有効にする

Hyper-V ホストマシンで Set-VMProcessor コマンドレットを使って、ExposeVirtualizationExtensions を $true にする。 これで、Hyper-V 上の対象VM で wsl2 + Docker Desktop for Windows が利用可能になる。

Set-VMProcessor -VMName "VMName" -ExposeVirtualizationExtensions $true

Windows 10 Home で WSL2 と Docker Desktop for Windows を動かす

開発環境では Docker で DB や各種バックエンドを動かすことが多いのですが、WFH が広がる中で自宅が Windows 10 Home で Docker Desktop for Windows 起動できないんだけど、何か手がないかと相談があったりなかったり。

以前試したときは問題なかったのですが、改めて最新の状況で試します。 また、wsl2 の仕組みから言って Hyper-V でホストしたWindows 10 Home でも動作するはずなのでそこも確認です。

Hyper-V に Windows 10 Homeをインストールしているのでその検証結果も知りたい人にも向けていいのではということで。

目次

更新履歴

  • 2020/5/17: Docker Stable に WSL2 対応がきたのを確認したのでEdge限定の記述を修正
  • 2020/5/28: Windows 10, version 2004 がきたので、Insider Preview の記述を修正

TL;DR

  • Windows 10 Version 2004 (2020 May Update)がGA されました。るまでは Insider Preview (Slow Ring でok) が必要
  • Docker Desktop fo Windows は Stableでok Edge が必要(Stableはよ)
  • wsl2 上の Linux ディストロで Docker を動かすのはまた別に

WSL2について

Docker Desktop for Windows をインストールする

* Insider Preview を有効にする (Slow Ring)

  • Windows Update で Windows 10 2004 にあげる
  • Windows Subsystem for Linux の有効化をしてWSL2を使う
  • Docker Desktop for Windows をインストール (Edge)

この時点で Windows バージョンは 1909

Insider Preview 前の Windows 10 バージョンは 1909

Insider Preview を Slowring で有効にする

2020/5/28 以降は、Windows Update で降りてくるので Insider Preview が不要です。

Insider PreviewをSlow Ring で有効化

適当に Microsoft アカウントを作成

Insider Preview の有効化 (ここでずっと変わらない場合がある)

Slow Ring を選択

Windows Update で Windows 10 2004 にあげる

Docker Desktop を Windows Home に入れるには、19018 以上である必要があるのでWindows Update をかける。 2時間近く時間がかかるので注意。

Windows Update を実行して Windows 10 Version 2004 にアップデート

これで Windows 10 Version 2004 となる。

Windows 10 バージョン 2004 を確認

Windows Subsystem for Linux の有効化をしてWSL2を使う

Docker for Desktop で実施されるので実行する必要がありません。もしもDocker Desktop for Windows をインストール後に間違って無効にした場合にぐらいしか使わない。

Windows Subsystem for Linux と Vitrual Machine Platformを有効にするため、Windows PowerShell を管理者で起動して、コマンドを実行。

Get-WindowsOptionalFeature -Online | where FeatureName -match linux | Enable-WindowsOptionalFeature -Online -NoRestart
Get-WindowsOptionalFeature -Online | where FeatureName -match virtual | Enable-WindowsOptionalFeature -Online

Windows 10 の機能を有効化

再起動される。

再起動される

wslコマンドが利用可能になっている。ディストロはインストール不要。

$ wsl -l
Linux 用 Windows サブシステムには、ディストリビューションがインストールされていません。
ディストリビューションは Microsoft Store にアクセスしてインストールすることができます:
https://aka.ms/wslstore

Docker Desktop for Windows をインストール

https://hub.docker.com/editions/community/docker-ce-desktop-windows/

記事公開時点は Edgeが必須でしたが、Stable にきたので Stableでokです。

リンクからDocker アカウントなしでEdgeをダウンロード

Edge なら Windows 10 Home でも 19018+ でインストール可能

もしWindows Update をかけていないと、Docker Desktop のインストールがコケる。

Docker Desktop requires Windows 10 Pro/Enterprise (15063+) or Windows 10 Home (19018+)

Windows 10 2004 になっていれば、WSL2 の有効化を効かれるのでそのままOK。

Enable WSL 2 Features は必ず有効にする

インストール後は再起動する。

再起動後に wsl2 のインストールが完了していないことが言われる。

wsl2 の有効化

Linux カーネル更新プログラムパッケージを入れる。

https://aka.ms/wsl2kernel のダウンロードから。

これで wsl2 が有効になる。

PC を再起動して、docker-desktop が見えるようになる。

$ wsl -l

左が Windows 10 Home on Hyper-V on Windows Server 2019 on Azure VM、右が Windows 10 Home on Hyper-V on Windows 10 Pro

ついでに wsl2 をデフォルトバージョンにしておく。

$ wsl --set-default-version 2

Docker の実行確認

実行できるか確認する

docker run --rm hello-world

どちらの環境でも docker run が可能

ボリュームマウントも問題ない

ボリュームマウントも問題なし

Docker の設定

ドライブ共有が不要になった

従来の Docker Desktop for Windows では ホストマシンとコンテナのドライブ共有が必要だったが、これは不要になった模様。 実際、なにもしなくてもボリュームマウントされた。Firewall や アンチマルウェアとのバトルがなくなってめでたい。

ボリュームマウントメニューがなくなった

Hyper-V 上の Windows 10 Home はだめなの?

問題なく動作する。 Windows 10 Pro 上の Hyper-V で Windows 10 Home をいれても wsl2 + Docker 動かすこともできるし、Azure 上のWindows Server 2019 上で Nested Hyper-V の上に Windows 10 Home をいれても wsl2 + Docker を動かすことができる。

もし CPU 側の 仮想化支援を有効にしていない場合、Windows 10 Home on Hyper-V on Windows Pro も Windows 10 Home on Nested Hyper-V on Windows Server 2019 (Azure) も動作しない。

Hyper-V や 物理マシンの Windows 10 Home で Dockerの起動が失敗する例

これが出た場合は、Hyper-V ホストマシンで Set-VMProcessor コマンドレットを使って、ExposeVirtualizationExtensions を $true にし忘れている。

Set-VMProcessor -VMName "VMName" -ExposeVirtualizationExtensions $true

物理マシンなら UEFI で CPU のAdvance メニューあたりに設定があるはず。