OSXでdocker使おうと思うと、現状だとVagrantのProviderでdocker使うかboot2docker使うかの2択だと思います。
今回はboot2dockerを利用している前提で、いろいろやってみました。
背景
dockerも1.0になったので、ちょっと本格的に利用してみようかとあっちこっちググりつつコンテナ作りに邁進してました。
この辺はちょっと省略しますけど、以下のような構成で 実行環境 on dockerを実現しています。
かなり簡略化してますけど、イメージは伝わると思います。
+application
+Dockerfile
+src
+...
+composer.json
FROM agen/appbase
VOLUME ["/app"]
$ 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
を素直に利用できません。
HOST <=> Container
なので、ちゃんとVOLUME
張れるんですけど、
HOST <=> VirtualBox <=> Container
なので、Hostから直接Containerに張れません。
この辺りの問題はissueにも上がってますし、解決方法はないこともないです。
boot2dockerに共有フォルダを張るまで
HOSTから直接張れないので、現状での当然の帰結として、VirtualBoxに共有フォルダ張ってContainerに伝播させます。
ところが、VirtualBoxで共有フォルダを使うためにはゲストOS(ここではCoreOS)にGuest Additions
を入れておく必要があります。
boot2dockerが標準で提供しているCoreOSにはGuest Additionsが含まれていないので、まずこれを準備しなければなりません。
ここで、boot2docker でボリュームの共有を行うを参考に、Guest Additions入りboot2dockerを入れることにします。
・・・はい、詳しくは上記リンクを参考で。
これで伝播までは完了。ちゃんと張れてることを確認できると思います。
本題
長かったんですけど、ここからが本題です。
上記までで共有フォルダのマウントまでできました。
コンテナにアプリ専用ユーザーでSSHでログインしてcomposer
で依存ライブラリをインストールしてみます。
$ ssh webapp@localhost -p 40153
webapp$ cd /app
webapp$ composer install
[RuntimeException]
vendor does not exist and could not be created.
インストールできません。
webapp$ pwd
/home/webapp
webapp$ ls -al
drwxr-xr-x 1 root root 442 Jun 29 10:31 app
はい、rootユーザーです。
実はVirtualBoxにrootで共有フォルダが張られているために、書き込み権限がないのです。
アプローチ
ここで解決方法は2種類あると思ってて、
- webappユーザーをrootに属させる
- webappユーザーでも書き込みできるよう共有フォルダの権限を変える
1は論外。何のためにユーザーを用意したのかわかりませんし、何よりこの問題はboo2dockerを利用する場合のみ発生します。
とすれば、選択肢は2のみ。幸いこれはVirtualBoxの問題なので、ググればいくらでも対応策は出てきます。
共有フォルダの権限を変える
自動化はあとで考えるとして、このアプローチで問題ないかを直接確かめていくことにします。
$ 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/
権限が変わっていることが確認できます。
続いて、コンテナから確認します。
$ 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
が通るはず。
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起動時に自動的に走るようにしたいんですけど。。。
あんまり手間かけたくない(正直言ってわからない)ので、今は暫定的に以下のようにしてます。
$ boot2docker up
$ boot2docker ssh "sudo mount -t vboxsf -o uid=1000,gid=1000,dmode=0755,fmode=0755 home /Users"
boot2dockerをラップして、勝手にこれを実行するようにはしてますけど、なんかほかにいい方法ないですか?