WindowsでもDocker Composeを使いたい

# ※追記1

Windowsでも動くようになったようです。
1.5.0リリースでWindows版バイナリが配布されるかもしれませんね。
https://github.com/docker/compose/issues/1085#issuecomment-142491609

# ※追記2

1.5.0 RC1でWindows版がリリースされました。
Docker Toolboxの次のリリースに期待！
https://github.com/docker/compose/releases/tag/1.5.0rc1

# ※追記3

> * Includes docker-compose on Windows

Docker Toolbox v1.9.0でWindowsにもdocker-composeが入りました！
https://github.com/docker/toolbox/releases/tag/v1.9.0

# はじめに

Dockerでマルチコンテナを管理するのに[Docker Compose](https://github.com/docker/compose/)が便利です。
しかし、[Epic: Windows support #1085](https://github.com/docker/compose/issues/1085)にある通り、Windowsネイティブではまだ動きません。
そこでBoot2DockerのTiny Core LinuxにDocker ComposeをインストールしてMinGWから使う方法を考えてみました。

# いきなりインストールスクリプト

面倒な人のためにいきなりインストールスクリプトです。
以下の内容を保存して`Boot2Docker Start`のショートカットからスクリプトを実行して再度`Boot2Docker Start`を開くと`docker-compose`を利用できます。
ただし、パスの扱いに注意が必要なので後述します。

```sh:install.sh
#!/bin/sh

VERSION=1.4.2
VAR_COMPOSE=/var/lib/boot2docker/docker-compose
BIN_COMPOSE=/usr/local/bin/docker-compose

boot2docker ssh "sudo curl -L -o ${VAR_COMPOSE} https://github.com/docker/compose/releases/download/${VERSION}/docker-compose-Linux-x86_64"
boot2docker ssh "sudo chmod +x ${VAR_COMPOSE}"
boot2docker ssh "sudo ln -fs ${VAR_COMPOSE} ${BIN_COMPOSE}"
boot2docker ssh "cat << EOL > bootlocal.sh
#!/bin/sh

if [ -x ${VAR_COMPOSE} -a ! -e ${BIN_COMPOSE} ]; then
  ln -s ${VAR_COMPOSE} ${BIN_COMPOSE}
fi
EOL
"
boot2docker ssh "sudo cp bootlocal.sh /var/lib/boot2docker/"
boot2docker ssh "rm -f bootlocal.sh"

if ! test -f ~/.bashrc || ! `grep -qE 'function +docker-compose' ~/.bashrc`; then
  cat << EOL >> ~/.bashrc
function docker-compose() { boot2docker ssh -t "docker-compose \${*}; exit 0"; }
EOL
fi
```

# 詳細インストール

## Boot2Dockerの仕組みについて

Boot2DockerのTiny Core Linuxはtmpfsでマウントされるので適当なパスにインストールしても再起動すると消えてしまいます。
ですが、boot2dockerのFAQに[Local Customisation (with persistent partition)](https://github.com/boot2docker/boot2docker/blob/master/doc/FAQ.md#local-customisation-with-persistent-partition)という項目があり、
`/var/lib/docker`と`/var/lib/boot2docker`は再起動してもファイルが消えないようです。
どうなっているのか詳しく追ってみると
![var.png](https://qiita-image-store.s3.amazonaws.com/0/8995/9a3f05af-df34-c92c-6863-72fdb0d26ee6.png)

![storage.png](https://qiita-image-store.s3.amazonaws.com/0/8995/2db13d55-58a9-057e-191e-0f78a560be5d.png)


2つのディレクトリの実体は`/mnt/sda1`にあり、仮想ディスクの`boot2docker-vm.vmdk`になっている事が分かります。

また、起動時に`/opt/bootscript.sh`から読み込まれるスクリプトが3つあるので後で使います。

| スクリプト                        | 用途                         |
|-----------------------------------|------------------------------|
| /var/lib/boot2docker/profile      | 環境変数などの設定           |
| /var/lib/boot2docker/bootlocal.sh | 起動時に同期して実行するもの |
| /var/lib/boot2docker/bootsync.sh  | 起動時に非同期に実行するもの |

## インストールファイル一覧

以下はインストールするファイル一覧です。

| Tiny Core Linuxのパス | 説明 |
|---|---|
| /var/lib/boot2docker/docker-compose | ダウンロードして追加 |
| /var/lib/boot2docker/bootlocal.sh | 追加 |
| /usr/local/bin/docker-compose | 起動時に追加 |

| MinGWのパス | 説明 |
|---|---|
| ~/.bashrc | aliasを追加 |

## Docker Composeをインストール

上で説明した通り、`/var/lib/boot2docker`の下にDocker Composeをインストールします。
MinGW側とTiny Core Linux側の作業を区別しにくいのでプロンプトで変えています。

* プロンプトが`$ `のコマンドはMinGWで実行します。
* プロンプトが`docker@boot2docker:~$ `のコマンドはTiny Core Linuxで実行します。

```shell-session
# Boot2DockerでTiny Core Linuxにログイン
$ boot2docker ssh


# Tiny Core Linuxにdocker-composeをダウンロード
docker@boot2docker:~$ sudo curl -L -o /var/lib/boot2docker/docker-compose https://github.com/docker/compose/releases/download/1.4.2/docker-compose-Linux-x86_64
docker@boot2docker:~$ sudo chmod +x /var/lib/boot2docker/docker-compose


# /usr/local/bin/docker-composeにシンボリックリンクを作成するスクリプトをbootlocal.shに追加
docker@boot2docker:~$ cat << EOL > bootlocal.sh
#!/bin/sh

if [ -x /var/lib/boot2docker/docker-compose -a ! -e /usr/local/bin/docker-compose ]; then
  ln -s /var/lib/boot2docker/docker-compose /usr/local/bin/docker-compose
fi
EOL
"
docker@boot2docker:~$ sudo cp bootlocal.sh /var/lib/boot2docker/
docker@boot2docker:~$ rm -f bootlocal.sh


# すぐ使えるようにシンボリックリンクを作成する
docker@boot2docker:~$ sudo ln -s /var/lib/boot2docker/docker-compose /usr/local/bin/docker-compose
```

```shell-session
# MinGWの.bashrcにdocker-composeのfunctionを追加
$ echo 'function docker-compose() { boot2docker ssh -t "docker-compose ${*}; exit 0"; }' >> ~/.bashrc
```

以上でインストール完了です。
MinGWを開き直して`docker-compose -h`を実行すればヘルプが表示されるはずです。
![compose.png](https://qiita-image-store.s3.amazonaws.com/0/8995/e6106f05-4f5a-0714-3840-951c25b16c03.png)

## Docker Compose実行時の注意

docker-composeを使えるようになったとは言えssh経由で実行しているのでdocker-compose.ymlなどはTiny Core Linuxから見える場所に置く必要があります。
Boot2Dockerはよく考えられていて、Windowsの`C:\Users`はTiny Core Linuxの`/c/Users`にマウントされているので次のようにパスを指定することができます。
このときパスの先頭の`/`を二重にします。詳しくは[Boot2Docker on WindowsでMinGWのパス変換を回避する](http://qiita.com/shiena/items/39bd32156b8d04ea5b92)を参照してください。

```shell-session
$ docker-compose -f /$HOME/docker-compose.yml up -d
```

逆にTiny Core Linuxから実行する場合はWindowsのユーザ名が分からないので環境変数を使うことができません。

```shell-session
docker@boot2docker:~$ docker-compose -f /c/Users/shiena/docker-compose.yml up -d
```