Docker を Bash on Ubuntu on Windows から使う

概要
---------------------------------------------------------------------

Bash on Ubuntu on Windows で Docker を使えない！
ただし Docker for Windows を Bash on Ubuntu on Windows から使うならできる。
~~そう Windows 10 Pro ならね。 :sunglasses:~~
※少々場当たり的なことをしていると思うので、
　よりよい方法をご存知でしたらお知らせください。 :bow:

Bash on Ubuntu on Windows で Docker デーモンは動かせないが
Docker クライアントをインストールして DOCKER_HOST 環境変数を設定し
Docker for Windows の Docker デーモンにアクセスすることはできる。
Docker を使うシェルスクリプトの動作確認をしたいときなどには便利。

ただし Docker Compose のボリュームの指定で相対パスを使えない。

- たとえば `volumes: ["./data:/data"]` のような指定ができないので不便。

手順
---------------------------------------------------------------------

中身の説明は、後述する。

1. Docker for Windows をインストールする。
   - Hyper-V が使えないと使えない。少なくとも Windows 10 Pro 以上。 
   - Windows 10 Home では使えない。
1. Docker for Windows の設定を行う。
   - Settings > General > Expose daemon on tcp://localhost:2375 without TLS にチェックを付ける。
   - Shared Drives > Shared にチェックを付け、Apply をクリックする。
1. Bash on Ubuntu on Windows に Docker をインストールする。
   - [公式の手順](https://docs.docker.com/engine/installation/linux/docker-ce/ubuntu/) の通りにインストールする。
      - なお、本記事の最後に補足資料として
        Docker インストール用の Ansible Playbook を掲載する。
1. Bash on Ubuntu on Windows にインストールした Docker クライアントの設定を行う。
   - **(ポイントA)** 次のように環境変数をセットする。
      - Docker for Windows の Docker デーモンに接続することになる。

        ```text
        DOCKER_HOST=tcp://localhost:2375
        ```
1. Bash on Ubuntu on Windows の設定を行う。
  - **(ポイントB)** Docker でマウントする必要のあるドライブについて、
    次のようにシンボリックリンクを作成する。
     - これは C ドライブの例。

        ```text
        ln -s /mnt/c /c
        ```
   - **(ポイントC)** 次のように `.bashrc` に追記する。

         ```
         if [ ${PWD:1:3} == mnt ]; then
           cd ${PWD:4}
         fi
         ```

手順の説明
---------------------------------------------------------------------

- Docker for Windows は Hyper-V を使うので Windows 10 Pro 以上でしか使えない。
  さらに言うと Hyper-V が動作する環境でなくてはならない。
- **(ポイントA)** Bash on Ubuntu on Windows に Docker をインストールすると、
  `docker` コマンドがインストールされる。
  `docker` コマンドは Docker デーモンとやり取りするクライアントプログラム。
  - `DOCKER_HOST` 環境変数を指定することで
    `docker` コマンドに問い合わせるべき Docker デーモンを伝える。
    **Docker デーモンは Bash on Ubuntu on Windows の中で動いている必要はなく、**
    **TCP で問い合わせればよい**のである。
- **(ポイントB)** Bash on Ubuntu on Windows は Windows のドライブを /mnt 以下にマウントする。
  しかし Docker for Windows でフォルダをマウントするためには、
  以下のいずれかの形式で指定しなければならない。
  Bash で使えるのは3つめの形式なので、これが使えるようにシンボリックリンクを作っている。
  - C:\path\to\folder
  - C:/path/to/folder
  - **/c/path/to/folder**
     - これが Bash on Ubuntu on Windows では
       `/mnt/c/path/to/folder` というパスになっているので、
       `/mnt/c` のシンボリックリンクを `/c` に作って
       `/c/path/to/folder` で参照できるようにしている。
- **(ポイントC)** Bash on Ubuntu on Windows は起動時の作業フォルダをもとに
  `/mnt/c/path/to/folder` といったディレクトリに移動してくれるが、
  本当は `/c/path/to/folder` に行きたい。つまり `/mnt` は要らない。
  そこで **Bash 起動時に /mnt から始まるパスのディレクトリにいたら
  /mnt 以下のパスに移動する**ように `.bashrc` に書く。

課題
---------------------------------------------------------------------

- 冒頭にも書いたが Docker Compose のボリュームの指定で相対パスを使えない。
  - `volumes: ["./data:/data"]` のような指定ができないので不便。
    Docker Compose はテストするときによく使うのでテストファイルをマウントしたかった。
- Visual Studio Code の統合ターミナルを Bash on Ubuntu on Windows にするには
  矢印キーが使えないなどの課題がある。これは別の話。
  たぶんこの [Issue](https://github.com/Microsoft/vscode/issues/10163)。
- そもそも Bash on Ubuntu on Windows 自体に課題がある。:frowning2:
  しばしば表示が崩れる。:expressionless:
- なお、そのまま起動するだけでは日本語が扱えない。
  [ConEmu](https://conemu.github.io/)を使うと日本語を入力できるようになる。

補足
---------------------------------------------------------------------

2017年9月現在、Docker をインストールする Ansible Playbook の `tasks` 部分は以下のような感じ。

```yaml
tasks:
- name: ensure docker's apt key exists
  become: true
  apt_key:
    url: https://download.docker.com/linux/ubuntu/gpg
    id: 9DC858229FC7DD38854AE2D88D81803C0EBFCD88
- name: ensure docker's apt repository exists
  become: true
  apt_repository:
    repo:  deb https://download.docker.com/linux/ubuntu xenial stable
    filename: docker.list
- name: install the latest version of docker
  become: true
  apt:
    name: docker-ce
  state: latest
```

2016年11月頃は以下のような感じだった。

```yaml
tasks:
- name: ensure docker's apt key exists
  become: true
  apt_key:
    keyserver: p80.pool.sks-keyservers.net
    id: 58118E89F3A912897C070ADBF76221572C52609D
- name: ensure docker's apt repository exists
  become: true
  apt_repository:
    repo:  deb https://apt.dockerproject.org/repo ubuntu-trusty main
    filename: docker.list
- name: ensure docker is at the latest version
  become: true
  apt:
    name: docker-engine
    state: latest
```

Docker Compose のインストールについては、以下のような感じ。

```
tasks:
- name: ensure docker-compose is at the latest version
  pip:
    name: docker-compose
    state: latest
  become: true
```