dockerにvolumeでソースコードを共有しつつcomposerでパッケージをインストールしたときの話 on OSX


OSXでdocker使おうと思うと、現状だとVagrantのProviderでdocker使うかboot2docker使うかの２択だと思います。
今回はboot2dockerを利用している前提で、いろいろやってみました。

# 背景
dockerも1.0になったので、ちょっと本格的に利用してみようかとあっちこっちググりつつコンテナ作りに邁進してました。
この辺はちょっと省略しますけど、以下のような構成で **実行環境** on dockerを実現しています。
かなり簡略化してますけど、イメージは伝わると思います。

```
+application
 +Dockerfile
 +src
  +...
  +composer.json
```

```:Dockerfile
FROM agen/appbase
VOLUME ["/app"]
```

```bash
$ docker build -t agen/app .
$ docker run -i -t -P -v `pwd`/src:/app agen/app /bin/bash
```

ここで、`agen/appbase`ではnginxやPHP-FPMなどの準備がすべて済んでいて、 **アプリケーション専用のユーザー** が用意されていて、ドキュメントルートである`/app`にアプリケーションが配置されていればアプリケーションが動く、というところまで準備が済んでいるとします。
なお、実行環境と書いた通り、このコンテナの上で開発する気はさらさらありません。ホストで`src`以下をごちゃごちゃします。

多分`agen/appbase`でEXPOSEされてる80にアクセスすると、アプリケーションが動く様が観察できるでしょう。

・・・ネイティブでdockerを動かしているUbuntuならば。

# boot2dockerの場合
MacはネイティブでDockerを動かすことはできないので、上述したboot2dockerを利用します。
で、boot2dockerの仕組み上、`VOLUME`を素直に利用できません。

```:Ubuntuの場合
HOST <=> Container
```

なので、ちゃんと`VOLUME`張れるんですけど、

```:boot2dockerの場合
HOST <=> VirtualBox <=> Container
```

なので、Hostから直接Containerに張れません。
この辺りの問題はissueにも上がってますし、解決方法はないこともないです。

# boot2dockerに共有フォルダを張るまで
HOSTから直接張れないので、現状での当然の帰結として、VirtualBoxに共有フォルダ張ってContainerに伝播させます。
ところが、VirtualBoxで共有フォルダを使うためにはゲストOS（ここではCoreOS）に`Guest Additions`を入れておく必要があります。
boot2dockerが標準で提供しているCoreOSにはGuest Additionsが含まれていないので、まずこれを準備しなければなりません。

ここで、[boot2docker でボリュームの共有を行う](http://qiita.com/superbrothers/items/1095ce71da4d425b6f36)を参考に、Guest Additions入りboot2dockerを入れることにします。

・・・はい、詳しくは上記リンクを参考で。

これで伝播までは完了。ちゃんと張れてることを確認できると思います。

# 本題
長かったんですけど、ここからが本題です。
上記までで共有フォルダのマウントまでできました。
コンテナにアプリ専用ユーザーでSSHでログインして`composer`で依存ライブラリをインストールしてみます。

```bash
$ ssh webapp@localhost -p 40153
webapp$ cd /app
webapp$ composer install
  [RuntimeException]
  vendor does not exist and could not be created. 
```

インストールできません。

```bash
webapp$ pwd
/home/webapp
webapp$ ls -al
drwxr-xr-x 1 root   root    442 Jun 29 10:31 app
```

はい、rootユーザーです。
実はVirtualBoxにrootで共有フォルダが張られているために、書き込み権限がないのです。

# アプローチ
ここで解決方法は２種類あると思ってて、

1. webappユーザーをrootに属させる
2. webappユーザーでも書き込みできるよう共有フォルダの権限を変える

1は論外。何のためにユーザーを用意したのかわかりませんし、何よりこの問題はboo2dockerを利用する場合のみ発生します。
とすれば、選択肢は2のみ。幸いこれはVirtualBoxの問題なので、ググればいくらでも対応策は出てきます。

# 共有フォルダの権限を変える
自動化はあとで考えるとして、このアプローチで問題ないかを直接確かめていくことにします。

```bash
$ boot2docker ssh
docker$ id
uid=1000(docker) gid=50(staff) groups=50(staff),100(docker)
docker$ sudo mount -t vboxsf -o uid=1000,gid=1000,dmode=0755,fmode=0755 home /Users
docker$ ls -al /Users
drwxr-xr-x    1 docker   1000           374 Jun 17 13:17 Guest/
drwxr-xr-x    1 docker   1000           170 Jun 17 13:28 Shared/
drwxr-xr-x    1 docker   1000          1360 Jun 30 05:54 agen/
```

権限が変わっていることが確認できます。

続いて、コンテナから確認します。

```bash
$ ssh webapp@localhost -p 40153
webapp$ pwd
/home/webapp
webapp$ ls -al
drwxr-xr-x 1 webapp webapp  510 Jun 30 05:52 app
```

こちらも意図通りです。
ですので、これで`composer install`が通るはず。

```bash
webapp$ cd app
webapp$ composer install
Loading composer repositories with package information
Installing dependencies (including require-dev)
...
Writing lock file
Generating autoload files
Generating optimized class loader
Compiling common
webapp$ ls -al
drwxr-xr-x 1 webapp webapp   782 Jun 30 05:53 vendor
webapp$ exit
$ pwd
/Users/agen/application
$ ls -al src
...
drwxr-xr-x  23 agen  staff    782  6 30 14:53 vendor
```

通りました。無事にインストールもできていて、かつ権限も問題なさそうに見えます。

# 自動化
この設定は、`boot2docker restart`しちゃうと当然のように消えちゃいます。
なので、できればboot2docker起動時に自動的に走るようにしたいんですけど。。。
あんまり手間かけたくない（正直言ってわからない）ので、今は暫定的に以下のようにしてます。

```bash
$ boot2docker up
$ boot2docker ssh "sudo mount -t vboxsf -o uid=1000,gid=1000,dmode=0755,fmode=0755 home /Users"
```

boot2dockerをラップして、勝手にこれを実行するようにはしてますけど、なんかほかにいい方法ないですか？