🐳

DockerのバックエンドにVMware Workstation Playerを使う

2020/12/22に公開

https://qiita.com/advent-calendar/2020/sgg

この記事は SGG(すごくなりたいがくせいぐるーぷ) Advent Calendar 2020 22日目の記事です。

はじめに

今年の上半期、Windows 10 Home でも、 Docker Desktop for Windows のバックエンドとしてWSL2が使えるようになりました。DockerをWSL2上で動かすために「Windows ハイパーバイザー プラットフォーム」を有効化する必要があるのですが、Hyper-Vと同じ扱いとなり、VMware Workstation PlayerのVT-x/EPT の仮想化[1]機能を有効にすると起動ができなくなってしまいます[2]。そこで、VT-x/EPTが有効な仮想マシンを起動するために、Docker Desktop for Windows でバックエンドに VMware Workstation Playerを使えるようにしたいと思います。

サイドチャネルの緩和
仮想 Intel VT-x/EPT
VT-x/EPT 仮想化を有効にすると起動できない

環境

  • Windows 10 Home 20H2
  • Docker Desktop for Windows 3.0.0
  • VMware Workstation 16 Player 16.1.0

※ 本文中では以下の通り設定します。適宜読み替えてください。

項目
VMのOS ArchLinux
VMのNetBIOS名 dockersrv
Dockerのポート番号 2375

手順

1. [Windows] ハイパーバイザー機能の無効化

まずはハイパーバイザー機能を無効化します。Hyper-Vの無効化と同じコマンドです。

コマンドプロンプト/PowerShell(管理者)
> bcdedit.exe /set hypervisorlaunchtype off

コマンドの実行後、PCを再起動します(ブート設定を書き換えているため)。

2. [VM] Dockerを仮想マシンで動かす

VMware Workstation Player上にDockerを動かす仮想マシンを作成します。Linux系であればどのディストリビューションを利用しても変わりはない[3]と思います。なお、詳細なOSのセットアップ、Dockerのインストール手順は省略します。

3. [VM] Dockerの起動設定の変更

Dockerのサービス起動設定(docker.service)を変更し、Windowsからアクセスできるようにします。

docker.service
[Service]
# ExecStart=で始まる行の、 -H の次の引数を変更します
# ポート番号は2375とします
ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 --containerd=/run/containerd/containerd.sock
# tcp://0.0.0.0:ポート番号

変更後、Dockerを再起動します。

Shell(root)
# systemctl restart docker

Dockerが自動起動するように設定します。

Shell(root)
$ systemctl enable docker

Dockerの起動を確認します。

Shell
$ docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

$ docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
0e03bdcc26d7: Pull complete
Digest: sha256:1a523af650137b8accdaed439c17d684df61ee4d74feac151b5b337bd29e7eec
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

4. [VM] NetBIOS名の設定

NetBIOS名を設定することで仮想マシンのIPアドレスを気にせずDockerを使用できます。

sambaをインストールし、/etc/smb.conf (ディストリビューションによっては/usr/local/samba/lib/smb.conf)を編集します。

smb.conf
[global]
# NetBIOS名をdockersrvとしています
netbios name = dockersrv

変更後、nmbdを再起動します。

Shell(root)
# systemctl restart nmb

5. [Windows] 環境変数の設定

DOCKER_HOST=tcp://dockersrv:2375
# tcp://NetBIOS名もしくはIPアドレス:ポート番号

DockerのCLIが仮想マシンで動くサーバーを利用するように以上の値を設定します。

コマンドプロンプト/PowerShell(管理者)
> setx.exe DOCKER_HOST tcp://dockersrv:2375
# システム環境変数として設定する場合は末尾に -m を追加

(6. [Windows] VM自動起動の設定)

Docker専用として仮想マシンを作成した場合は、仮想マシンがWindowsの起動に合わせて起動するよう設定すると便利です。

指定するコマンドライン
"C:\Program Files (x86)\VMware\VMware Player\vmrun.exe" -T player start "vmxファイルのパス" nogui

引数に指定するvmxファイルは、仮想マシン設定 > オプションタブ > 全般 > ワーキングディレクトリ内に保存されています。

確認

コマンドプロンプト/PowerShell
> docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

> docker run hello-world
docker run hello-worldの実行結果
Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

一度仮想マシンで実行しているため、はじめの

Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
0e03bdcc26d7: Pull complete
Digest: sha256:1a523af650137b8accdaed439c17d684df61ee4d74feac151b5b337bd29e7eec
Status: Downloaded newer image for hello-world:latest

が表示されません。

まとめ

以上でDockerを動かしながら仮想マシン上で仮想マシンを動かせるようになりました。
仮想マシン上でQEMUとKVMを組み合わせるなど、使いみちをぜひ模索してみてください。

余談

この方法を模索している間に、僕がどうしてVT-x/EPTの仮想化を有効化しようと思ったのかは忘れてしまいました。

脚注
  1. Intelの仮想化技術 VT-x/EPT を仮想マシンで使えるようにすることで、 仮想マシン上でのKVMの利用などを可能にします。なお、AMD ↩︎

  2. 複数の仮想化ソフトウェアが同時に VT-x/EPT を使えないことに起因するそうです。 ↩︎

  3. Docker専用にするのであればGUIのないディストリビューションを選ぶとCPU/メモリの使用量を抑えられます。 ↩︎

  4. 僕の環境ではNAT設定にするとうまく動きませんでした…。 ↩︎

Discussion