Dockerコンテナの分割は開発時はプロセス毎にしたほうがいい。
Contents
tl; dr
https://github.com/kotamat/laravel-docker-cluster
背景
一つのプロジェクトには、いろんなミドルウェアが入ってくる事があります。例えば、PHPの場合、よく言われるのはLAMPというものですが、これは
- Linux
- Apache
- Mysql
- PHP
を一つにまとめた略称であり、これらがあることによって、PHPのWebアプリケーションが実行可能な状況になります。(もちろんMysqlなくてもPHPは動きますが、DataStoreが無いWebアプリケーションはそんなに無いと思われるので、この中に入れているのでしょう。)
Dockerを初めて使うときは、上記をすべてインストールした一つのimageに固め、一つのコンテナで動作させようと思うかもしれないですが、そうしてしまうと、一つのミドルウェアのバージョンだけを上げたいと思っても、再度すべてビルドし直さなければなりません。
もしyum install -y mysql
コマンドのようにバージョン指定せずインストールしていた場合、意図せず他のミドルウェアのバージョンが上がってしまうかもしれません。
また、開発時でしか使わないようなミドルウェアを入れたりする場合、アプリケーション側のイメージとは分離してミドルウェアをいれ、実行する環境を物理的に分けたいという場面に出くわすかもしれません。
今回例に上げるLaravelでは、開発補助も含め複数のミドルウェア、ツールが存在するため、これらを物理的に分ける方法を考えたいと思おいます。今回は下記を分離します。
- artisan: Controllerの自動生成やmigration等のcliツール
- elixir: nodejsベースのasset系ファイル(js, css)の生成、browserSyncなどのブラウザとの連携ツール、実態はgulpタスク
- npm: nodejsのライブラリ管理ツール。
- composer: phpのライブラリバージョン管理ツール
- php-fpm: phpのcgiミドルウェア、PHPアプリケーションとして使う
- nginx: php-fpmへのリバースプロキシ・サーバー
- mariadb: データストア
Volume Mount
DockerにはDockerVolumesというボリュームマウントの仕組みがあります。
|
|
上記の様に-v
オプションを指定すれば、現在のディレクトリをubuntuコンテナの/backupディレクトリにマウントでき、あたかもubuntuコンテナ内では/backupディレクトリが存在する一つのコンテナのように動作します。
明示的にディレクトリを指定したくない場合はimage作成時にvolumeの割り当てを行います。
|
|
Volume Container
上記のマウントの仕組みを応用した例としてVolume Containerというものを作成してデータを永続化しようというパターンがよく使われます。このパターンを使うときはdocker-composeを使用すると、一連の流れを一つのファイルにまとめられて便利です。下記のように書きます。
|
|
volumes_fromでvolume containerのコンテナサービス名を指定し、そこに割り当てられているボリュームを共有します。
こうすることで、もしdb
サービスが停止したとしてもbusyboxコンテナに割り当てられている/var/lib/mysqlが存命しているので、再起動すればデータは復活します。
プロセス毎に分けてみる。
上記背景で述べたプロセス毎に分けると下記の様になります。
|
|
各サービスでbuildオプションを指定しているのは、前述のバージョンアップに備えるためにDockerfileを変更可能にするためで、下記のディレクトリ構成でDockerfileを管理しています。チーム運用する場合は、どこかのレジストリにimageを上げて、docker pull できる形で運用した方がいいと思います。
|
|
プロセス毎に実行してみる。
まず、デーモン化するべきコンテナと都度実行でいいコンテナを分けてみましょう。
- デーモン化するべきコンテナ
- nginx
- fpm
- db
- 都度実行で良いコンテナ
- composer
- gulp
- npm
上記認識を元にdocker-compose up -d
を実行してみると
|
|
上記のようにデーモン化するべきコンテナのみプロセスとして動いている事が確認できます。
都度実行でいいコンテナに関しては、docker run --rm
コマンドを使用することで、実行後コマンド用コンテナが削除され、クリーンな運用をすることができます
都度実行例
|
|
まとめ
- コンテナの分け方をプロセス毎にすることによって必要なタイミングで必要なコマンドを実行するイメージを作成でき、アプリケーションのイメージをクリーンな状態で保つ事ができる。
- また各プロセス毎のミドルウェアのバージョンアップ、メンテナンスも、設定ファイルが別れているので、簡単に編集が可能。
Author kotamat
LastMod 2016-12-06