WSL + Docker Toolbox(docker-machine) + docker-compose の環境構築

Windows 上に構築した Docker Toolbox の Docker Machine を WSL 内の `docker-compose` コマンドで操作できるようにします。

## Windows に必要なものをインストール

Chocolatey でいろいろインストールします。別に Chocolatey じゃなくても良いです。

Docker Toolbox には VirtualBox が必要なのでインストールします。また、VirtualBox をアップデートすると結構な確率で Docker Machine が動かなくなったりしたので、ピンしてバージョンを固定します（バージョナップはアンインストール→インストール）。

```sh
choco install -y virtualbox
choco pin add -n virtualbox
```

Docker Toolbox をインストールします。

```sh
choco install -y docker-toolbox
```

## WSL に必要なものをインストール

WSL に Docker をインストールします。ubuntu 用のパッケージリポジトリがあるのでそちらからインストールします。

- https://docs.docker.com/install/linux/docker-ce/ubuntu/#set-up-the-repository

```sh
sudo apt-get update
sudo apt-get install apt-transport-https ca-certificates curl software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo apt-key fingerprint 0EBFCD88
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
sudo apt-get update
sudo apt-get install docker-ce
```

`docker-compose` と `docker-machine` もインストールします。それぞれ Github にビルド済バイナリがあるのでダウンロードしてパスの通ったところに配置します。

- https://github.com/docker/compose/releases/latest
- https://github.com/docker/machine/releases/latest

## Docker Machine を作成

Windows 側で Docker Machine を作成します。`--virtualbox-share-folder` を指定しているのがポイントです。これがないと WSL のパスとの対応が取れなくなります。詳細は後述します。

```sh
docker-machine.exe create default --driver=virtualbox \
    --virtualbox-hostonly-cidr '192.168.99.1/24' \
    --virtualbox-share-folder 'c:\Users:/mnt/c/Users'
```

次に、WSL の `docker-machine` コマンドで↑で構築した Docker Machine を操作できるようにインポートします。`--driver=generic` を指定すれば実行中のホストを SSH 経由で `docker-machine` で制御できるようになります。`--generic-ip-address` や `--generic-ssh-key` では Windows 側の Docker Machine のものを指すように指定します。

```sh
docker-machine create default --driver=generic \
    --generic-ssh-user="docker" \
    --generic-ip-address="$(docker-machine.exe ip)" \
    --generic-ssh-key="/mnt/c/Users/$USER/.docker/machine/machines/default/id_rsa"
```

これは必須ではないです。インポートすると言っても `docker-machine start` や `docker-machine stop` は `--driver=generic` だとできないため、`docker-machine ip` `docker-machine ssh` ぐらいしか使わないと思います。これぐらいなら Windows 側の `docker-machine.exe ip` とかを実行しても対して変わらないです。

WSL の `docker` コマンドのための環境変数を設定します。

```sh
docker-machine env > "$HOME/.docker/env"
echo 'source "$HOME/.docker/env"' >> ~/.bash_profile
source "$HOME/.docker/env"
```

WSL の `docker` コマンドから Windows の docker-machine にアクセスできていることを確認します。

```sh
docker ps
docker run --rm hello-world
```

マウントもできることを確認しておきます。

```sh
docker run -v $PWD:/app:ro --rm alpine ls /app
```

最後に、WSL側の Docker Machine の秘密鍵や証明書等のファイルを Windows 側の Docker Machine にコピーしておきます。

```sh
rsync ~/.docker/machine/machines/default/ \
    "/mnt/c/Users/$USER/.docker/machine/machines/default/" \
    --exclude config.json -av
```

WSL 側に `--driver=generic` で Docker Machine をインポートしたときに Docker Machine の中で動いている Docker Engine にアクセスするための秘密鍵や証明書が更新されているので、そのままだと Windows 側の `docker-machine.exe` コマンドでいくつかの操作ができなくなります。

ただ、`docker-machine.exe start` や `docker-machine.exe stop` は秘密鍵や証明書は無くてもできるので、あまり困りません（Windows 側の `docker-machine.exe` ではこれぐらいの操作しかしない）

## スタートアップ

スタートアップで Docker Machine を開始すると良いです。下記でスタートアップフォルダを開いて・・

```sh
explorer.exe shell:startup
```

次のようなショートカットを登録すれば OK です。

```sh
docker-machine.exe start
```

## パスについて

`docker-machine` はデフォルトではホスト（Windows）のディレクトリをゲスト（virtualbox）に `c:\Users -> /c/Users` のようにマウントします。

Windows 上で `docker-compose` コマンドを使う分にはこれで十分です。`docker-compose` は `c:\Users` のようなパスを自動的に `/c/Users` に読み替えます（`COMPOSE_CONVERT_WINDOWS_PATHS=true` 環境変数が設定されていればですけど、`docker-machine.exe env` に含まれています）。

しかし WSL から使う場合はこれだと不都合です。WSL ではホストのディレクトリが `c:\Users -> /mnt/c/Users` のようにマウントされます。

したがって WSL で `/mnt/c/Users/ore/vol` などをマウント元として指定するためには virtualbox でも `c:\Users` が `/mnt/c/Users` にマウントされている必要があります。

なので docker-machine の作成時に `--virtualbox-share-folder` で次のように指定しています。

```sh
docker-machine.exe create default --driver=virtualbox \
    --virtualbox-hostonly-cidr '192.168.99.1/24' \
    --virtualbox-share-folder 'c:\Users:/mnt/c/Users'
```

なお、↑のように Docker Machine を作ると、逆に Windows 上の `docker-compose.exe` ではパスの対応がとれなくなってしまうので使い物にならなくなります。PhpStorm で `docker-compose` を設定するときは Windows 上の `docker-compose.exe` が使用されるので注意が必要です。

WSL の設定でホストのディレクトリが `c:\Users -> /c/Users` とマウントされるようにしても良いのかもしれません、これなら WSL と Windows の両方の `docker-compose` を活かすことができるかも（未確認）。

## さいごに

Docker for Windows は Hyper-V が必要で、Hyper-V は VirtualBox と共存できなくて、VirtualBox は vagrant に必要なので、Docker for Windows は使ってません。なので Docker for Windows を WSL から使えるかどうかはわかりません。

vagrant はもうほとんど使っていないので、もし WSL から Docker for Windows が使えるなら Docker for Windows に乗り換えたほうが良いかもしれません（ただしそれでパスの問題が解決するかはわからない）。