Windows10にDockerをインストールしてbusyboxコンテナが動くようになるまで

# Windows10にDockerをインストールしてbusyboxコンテナが動くようになるまで

ずいぶん罠が多かったので、下記の完成形にあるコマンドが問題なく実行できるようになるまでをメモする。

## TL; DR

Docker Desktop for WindowsをWindows10にインストールする場合は

- デフォルトのLinux containersではなくWindows containersを選択する
- Experimental featureを有効化する
- WindowsのHyper-Vとコンテナ機能GUI（コントロールパネル）経由ではなく、CUI（PowerShell）経由で有効化する

と上手くいきそう。

## 完成形

Dockerのバージョンは下記にある通り`v18.09.2`CE（Stable版）。
後述のように、Experimental featureを有効化する必要があった。

```
> docker version
Client: Docker Engine - Community
 Version:           18.09.2
 API version:       1.39
 Go version:        go1.10.8
 Git commit:        6247962
 Built:             Sun Feb 10 04:12:31 2019
 OS/Arch:           windows/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          18.09.2
  API version:      1.39 (minimum version 1.24)
  Go version:       go1.10.6
  Git commit:       6247962
  Built:            Sun Feb 10 04:28:48 2019
  OS/Arch:          windows/amd64
  Experimental:     true

> docker run --rm busybox echo hello_world
Unable to find image 'busybox:latest' locally
latest: Pulling from library/busybox
697743189b6d: Pull complete
Digest: sha256:061ca9704a714ee3e8b80523ec720c64f6209ad3f97c0ff7cb9ec7d19f15149f
Status: Downloaded newer image for busybox:latest
hello_world

```

ただし、この状態になっても、Linux container用のデーモンに切り替える（タスクバーのDocker Desktopアイコンを右クリック→`Switch to Linux containers`）とDocker Desktopの起動に失敗する。

## 環境

- OS: Microsoft Windows 10 Pro
- 認証付きプロキシ内（環境変数のHTTP_PROXYとHTTPS_PROXYに`http://ユーザー名:パスワード@proxy.com:ポート番号`形式で設定済み
- ハードウェア: Microsoft Surface Pro 6

## 手順

###  Docker Desktop for Windowsのインストール

Docker IDでログインし、普通にStable版をダウンロード＆インストールする。

**このときデフォルトのLinux containersを選択したが、ここでWindows containerを選択しておくと、下記の起動エラーが起こらなかったように見える。（未検証）**

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

インストーラーがWindowsのHyper-Vとコンテナ機能を有効にするため、OSが再起動する。

しかし、起動後Docker Desktopが下記のエラーで起動に失敗する：

```
Unable to start: ユーザー設定変数 "ErrorActionPreference" または共通パラメーターが Stop に設定されているため、実行中のコマンドが停止しました。'MobyLinuxVM' は起動できませんでした。(仮想マシン ID 15E56AF6-2ED1-4955-BEEC-B280F98867F6)
Start-MobyLinuxVM、<ファイルなし>: 行 296
<ScriptBlock>、<ファイルなし>: 行 412
   場所 Docker.Core.Pipe.NamedPipeClient.Send(String action, Object[] parameters) 場所 C:\workspaces\stable-18.09.x\src\github.com\docker\pinata\win\src\Docker.Core\pipe\NamedPipeClient.cs:行 36
   場所 Docker.Actions.<>c__DisplayClass28_0.<SwitchDaemon>b__0() 場所 C:\workspaces\stable-18.09.x\src\github.com\docker\pinata\win\src\Docker.Windows\Actions.cs:行 305
   場所 Docker.WPF.TaskQueue.<>c__DisplayClass19_0.<.ctor>b__1() 場所 C:\workspaces\stable-18.09.x\src\github.com\docker\pinata\win\src\Docker.WPF\TaskQueue.cs:行 59
```



### PowerShellからのHyper-V・コンテナ機能再有効化

コントロールパネル→プログラムと機能→Windowsの機能の有効化または無効化を選択し、「Hyper-V」と「コンテナ」のチェックを外して再起動する。

再起動後、PowerShellを管理者権限で起動し、以下のコマンドを実行する：

```
> Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All
# 再起動を促されるので再起動した後、以下を実施
> Enable-WindowsOptionalFeature -Online -FeatureName Containers -All
```

参考: https://github.com/docker/for-win/issues/1221#issuecomment-337770743

まだDocker Desktopの起動に失敗する。

### Hyper-V Virtual Machine Management サービス再起動

PowerShellを管理者権限で起動し、以下のコマンドを実行する：

```
> net stop vmms
> net start vmms
```

ここまでやるとDocker Desktopの起動に成功する。

しかし、`docker version`を実行すると以下のようなエラーメッセージが出る：

```
> docker version
Client: Docker Engine - Community
 Version:           18.09.2
 API version:       1.39
 Go version:        go1.10.8
 Git commit:        6247962
 Built:             Sun Feb 10 04:12:31 2019
 OS/Arch:           windows/amd64
 Experimental:      false
error during connect: Get http://%2F%2F.%2Fpipe%2Fdocker_engine/v1.39/version: open //./pipe/docker_engine: The system cannot find the file specified. In the default daemon configuration on Windows, the docker client must be run elevated to connect. This error may also indicate that the docker daemon is not running.
```

### PowerShellからのDocker Daemon切替（Linux→Windows）

どういうわけか、CLI経由でDaemonをLinuxコンテナ用からWindowsコンテナ用に切り替えるとエラーが解消されるらしい：

```
> cd "C:\Program Files\Docker\Docker"
> ./DockerCli.exe -SwitchDaemon
```

参考: https://github.com/docker/for-win/issues/1825#issuecomment-433719346

確かに`docker version`してもエラーは出なくなったが、Linuxコンテナは実行できない。

```
> docker run --rm busybox echo hello_world
Unable to find image 'busybox:latest' locally
latest: Pulling from library/busybox
docker: no matching manifest for unknown in the manifest list entries.
See 'docker run --help'.
```

### Docker DaemonのExperimental Feature有効化

タスクバーのDocker Desktopアイコンを右クリックし、Settingsを選択する。

DaemonメニューのBasicとなっているスイッチをAdvancedにスライドする。
参考: https://halkichi-web.hatenablog.com/entry/2018/08/23/124454

Docker再起動後、問題なくbusyboxコンテナが実行できることを確認：

```
> docker run --rm busybox echo hello_world
Unable to find image 'busybox:latest' locally
latest: Pulling from library/busybox
697743189b6d: Pull complete
Digest: sha256:061ca9704a714ee3e8b80523ec720c64f6209ad3f97c0ff7cb9ec7d19f15149f
Status: Downloaded newer image for busybox:latest
hello_world
```

他のコンテナも実行可能：

```
> docker run --rm -it ototadana/nlp-jp bash
Unable to find image 'ototadana/nlp-jp:latest' locally
latest: Pulling from ototadana/nlp-jp
8ad8b3f87b37: Pull complete
1ea481c977b3: Pull complete
c49f1fa31376: Pull complete
2840b8cb5b3f: Pull complete
3da718da5013: Pull complete
8901c1789308: Pull complete
b6c16d69e588: Pull complete
b63e6e3a5fee: Pull complete
49c57988feb4: Pull complete
8c4df89b9522: Pull complete
3838b41d340b: Pull complete
Digest: sha256:c26ffe74a2ead80906ed3fc3b9b1a384f6a6235da93299f890ed1eebf5dcbf92
Status: Downloaded newer image for ototadana/nlp-jp:latest
root@3099d19b492a:/#
```

## 付録: Windowsコンテナにディレクトリをマウントする方法

以下のように`-v`オプションで任意のディレクトリを指定するだけでOK。

```
> docker run -v C:\OS側のディレクトリパス:/コンテナ上のマウント先 -it --rm ubuntu bash
```

Web検索すると「Docker DesktopのSettingsからShared Volumeを設定する」という文言が出てくるものの、Shared Volumeというメニューが無くて焦るが、Shared VolumeはLinuxコンテナを利用しているときの機能らしい。
参考: https://forums.docker.com/t/shared-drives-option-not-showing-up-in-docker-for-windows-settings/35725/4

## 追記: しばらくしたら動かなくなったので再インストール

その後久しぶりにDockerを使おうとしたら、なぜかどのコンテナも実行できなくなっていたため、以下の手順で最新版（19.03.1）をインストールした。

1. 最新のDocker Desktopパッケージをダウンロード（v19.03.1）
2. インストーラー起動。このときUse Windows containersのオプションにチェックを入れる
3. Docker Desktopが立ち上がったら、settingsからExperimental Featuresを有効化する
4. コマンドプロンプトを立ち上げ、`docker run --rm busybox echo hello_world` で動作確認