tDiary を docker で動かす
この日記のサーバ移転に向けて、新しい環境をどうするか考えている。いままで通り、普通に nginx と unicorn で動かしても面白くないので、何か新しくしたい。いままで運用しての悩みは、日記サーバはたまにしかログオンしないので、すぐに環境がどうなっていたか分からなくなってしまうこと。chefやantibleやitamaeなどの構成管理ツールを入れるのはオーバースペック。
そこで、いっそ docker で動かしてみようと思う。dockerは1年ほど前に少し動かした程度で、その時はまだ運用で使うにはハードルが高かった。あれから1年が経ち、1コンテナ1プロセスなどの運用パターンも確立しつつあるようなので、いい時期かもしれない。当時はmonitを使って複数プロセスを起動しようとしていたっけ。dockerは公式ドキュメントがよく出来ているので、 blog や qiita などの情報を探すよりも、まずは公式ドキュメントをじっくり読むのがよい。
Macでのdocker環境構築
いずれ、Linuxサーバ上で動かすことになるから、最初は vagrant を使って ubuntu core を入れてみた。 vagrant ssh で ubuntu core にログインして docker コマンドを動かしているうちは、これで良かった。でも、 Mac から Web ブラウザで接続しようとすると、ネットワークの設定が面倒になっちゃう(特に ubuntu core は vagrant 側のネットワーク設定が自動的に反映されない)。 docker の使い方を覚えたいのに、他のところで時間を使うのはもったいない。
という訳で、Install Docker on Mac OS Xで紹介されている boot2docker を使うことにした。 brew install boot2docker でインストールする。 VirtualBox を使って仮想化した Linux 上で docker を動かすので仕組みは vagrant + Linux + docker と同じだけど、いい感じにネットワーク設定されていたり、 boot2docker ip でIPアドレスを調べられたり、 Mac 側から docker コマンドが使えたり、 Mac と docker コンテナでファイルを共有できたりと、かゆいところに手が届いて便利。 VirtualBox の GUI を開けばどのようなネットワーク設定になっているか(NATとホストオンリーアダプタの二枚構成)も分かるので、いずれ vagrant + Linux + docker 構成に移すときの参考にもなる。
docker の使い方
さっきも書いたとおり、公式の The Docker User Guide - Docker Documentation がよくできているので、最初はこれをひと通りやって基本的な使い方を覚える。 docker は本体だけでなく周辺のエコシステムが熱いけど、まずは docker 本体の仕組みに慣れるのが良い。
tDiary を docker で動かす
docker の使い方に慣れてきたので、いよいよ tDiary を docker 上で動かしてみる。最初に悩むのは、ベースとなるイメージをどれにするか。最近は、公式の言語スタックが公開されているので、これを使うのが良さそう。公式の言語スタックについては、DockerHub公式の言語Stack | SOTAが参考になった。いや、この記事に限らずここのブログは参考になる情報ばかり。
もちろんRubyの公式イメージも用意されている。公式イメージを使うにしても、どのような環境なのか分からないと使えない。latest(2.2.2)のDockerfileでRubyがどのようにインストールされているかを調べて、さらにonbuildのDockerfileを読んでイメージの作り方を調べる。
だいたい分かったので、 tDiary の最小構成での docker イメージを作ってみた。まずは1つの docker イメージで動くよう、 unicorn も memcached も mongodb も使わずにしている。コンテナは揮発性の環境にするために、データディレクトリはVOLUMEを使ってホスト側と共有している。Dockerfileを用意したら、イメージをビルドする。
$ docker build -t machu/tdiary .
ruby-2.2.0イメージからスタートして、 tdiary new コマンドと bundler で必要な環境をセットアップし、 tdiary イメージの完成。次に作成したイメージから docker run コマンドでコンテナを起動する。
docker run -v "$(pwd)/data":/usr/src/app/data --rm -p 8080:9292 machu/tdiary
ホスト側のカレントディレクトリに日記用の data ディレクトリをマウントしている。 Linux のホストOSを意識せずに、普通にMac側とdocker側でディレクトリが共有される。このへんはboot2dockerが頑張っているみたい。詳しくはboot2dockerでのVolume問題が解決しそう | SOTAを参照。
イメージからコンテナを生成してブラウザでアクセスすると、ちゃんと日記が表示される。 tDiary を終了するとコンテナも削除される。コンテナが削除されても、日記データは Mac 側の data ディレクトリに残っている。毎回まっさらな環境から tDiary アプリが動くので、環境が担保されている安心感がある。揮発性の環境 (immutable infrastructure) の良さを少し実感した。
認証やログや Web サーバの連携や tDiary アップデートへの追従などはこれから。イメージを作りなおせば、最新の tDiary を使うようになっているけど、tDiary updateボタンのように簡単にアップデートできるようにしたい。docker composeも使うことになるだろう。
Dockerの使いどころ
すべてをコンテナで動かす!ようにはたぶんならなくて、僕は tDiary の開発も今までどおり Mac 上で rbenv を使うだろう。 docker は軽量とはいえ、イメージの作成とコンテナの起動が必要なので、書いてすぐに動く気軽さはなくなる。代わりに、コンテナが隔離&揮発性のおかげで、環境が綺麗であるのはメリット。 tDiary の開発でも、たまたまとある gem が入っていたので動いていた…というのも、たまにあったので。ローカルでは普通にコードを書いて、テストを通してGitHubにコミット後にコンテナ環境を作成、その後に日記サーバへコンテナをデプロイという流れで、日記サーバの環境を手元と同一にするところに使うのが良さそう。
参考にした情報
まだ読んでいないけど、WEB+DB PRESS Vol.86|技術評論社でもDocker特集をやっているみたい。