今更Dockerを使い始めて初日に感じたことメモ

2014年10月18日土曜日

この1年ぐらいTLの一部(というか割と多く)でDockerの話題が出て、Docker 1.0が出たとかMicrosoftともアライアンス組んだとかそういうニューストピックという認識はあったんだけど、取り立てて自分の手元での用途が無かったのでこれまで全く触ってなかった。

先週あたりからちまちまと東京メトロの オープンデータ活用コンテスト に取り組み始めて、軽い分析系のものをいくつか試作したい欲が湧いたところでDockerの機運が高まったので使い始めた。

まずはざっくりと勝手がわからないとつらい。
さらっと使ってみるには いまさら聞けないDocker入門 が良いと感じた。
ちょうど1.0がリリースされる前後に開始した連載で、1.0ベースの話が展開されている。
インストールから基本操作(pull, run, build, rm, rmi, exportあたり)は把握できた。




Dockerを触る前から不思議に感じていて、基本操作を試しているうちにより不思議に感じてきたのが「皆、コンテナ内で生成された重要データはどうやって永続化してるの」というあたりだった。
DockerといえばImmutable Infrastructureだ! 環境はバンバンぶっ壊すものだ! という先鋭的な向きもあるとは思うけど、そうは言っても全部ストレージはS3パイセンへ、というのはやっぱり辛い。
なんたって手元はさくらのクラウドにあるメモリ2GBのインスタンスで全部完結させたい。RDSもねぇ、ElastiCacheもねぇ、EC2を使う気これっぽっちもねぇ、という環境なのでこのへんは切実でもある。

まあきっと「処理主体としてのコンテナ」と「コンテナによって読み書きされるデータ」の標準的なレイアウトなんてのはなくて勝手ルールがいっぱいあるんだろうなーと、あまり期待しないところスタートであった。

多分世にあるDockerfileを読んでみるのが手っ取り早いんだろうと思って真っ先に読んだのは@futoaseさんの futoase/GrowthForecast (@futoaseさんには、某OSSへのパッチなど様々な場面でお世話になっている)。-v(--volume)でのボリューム割り当てによるコンテナ内部のデータの外部での永続化、-e(--env)での環境変数設定など、「あー、こういう流儀なのか」という納得が結構あった。

他にもいくつか読んでいくなかで、割と早い段階で持った疑問が
「自分は今、あんまりメモリが豊富でない環境でいくつかのサービスをホストしようとしてるんだけど、各コンテナでMySQL持つの?辛くね?」
ということだった。
まあ、Rubyのバージョン地獄をrvmで回避したり、「まだrvm使ってんの?普通rbenvだろ」って煽られたり、Node.js各バージョンをnodebrewで使い分けたりnpmで-gは滅多に使わなかったり、果ては「perlbrew使ってないの?マジで?」というご時世なイメージはあって。なんでもかんでも自家醸造の時代だよ、麺だって自作だよヌードルメーカーだよ!というのは分からなくもないんですけれど。

つまりライブラリ群の依存関係で深く傷つくぐらいなら色んなものをproject-wideに制限していこうという話で、そのイメージでいくと別段コンテナごとにMySQLサーバのプロセスを内部に抱えるのも違和感は少ないのかもしれない。

けれどまあまともに動かすならMySQLに最低100MBぐらいは持っていかれるでしょうと。ほほう、PHPですか、そのApacheはpreforkしてくださるんですか35MBメモリお召し上げですかと。

考えていくと、ここしばらくRaspberryPi(初期モデル、メインメモリはVRAM共有で256MB)環境でサーバをやり繰りしていた際についた貧乏症が出てきて「なるたけ共有で良い(こだわり設定でない)MySQLはひとつのコンテナに集約したいでしょう」 となる。

Dockerを使う上で、各アプリにぴったり合うミドルウェアをバージョンごと指定して確実に動かして快適性を得る、というのがモチベーションのそれなりに大きなエリアを占めてるはずなので、「じゃあこれPHPやめて書き直そう」とか「MySQLより小規模利用時にはメモリ消費の少ないデータストアに置き換えよう」とかは不毛。

かといってDockerのホスト側でMySQLを走らせるかというとそれは違うよなーと思ってた。

そんな時に眺めたのが sameersbn/redmine だった。Dockerfileを軽く眺めると、OSバージョンを固定(加えて、この場合は自分が使うのに最低限便利な構成にしたOSイメージを派生させてる)してあとは必要パッケージをいくつか追加してさっくりと完了しているように見える。
それでいてデータストアにはコンテナ内部のMySQLを使う方法(実際にはこれは古い利用方法で、後述のコンテナリンクが推奨される)、外部MySQLのアドレス/ポート/ID/PWをコンテナ起動時の環境変数で指定する方法、そしてコンテナリンク(--link)なる方法で別のコンテナとつないで使う方法が用意されてるらしかった。
まあ、もう少しちゃんと読むと 、この 初期化スクリプト がなかなかの規模でヒィとなったんだけど。

コンテナのリンクというキーワードまで到達したらもう少しで全体像が見えてくる感じがした。
公式ドキュメントの Linking Containers Together (ドキュメント自体は1.3のもののほうがかなり分かりやすいので概念理解向きだけど)を眺めて、これはリンクで参照される側とリンクする側の間でループバックインタフェースによる接続を張れるようにして、リンクで参照する側からは所定の環境変数を見ることで接続情報を把握して接続するらしいことがわかった。
もう10年以上、同サーバでPHP類とMySQLを同居させる時にはUnixDomainSocket経由でしか使ったことがなかったので、Dockerを最初にざっと眺めた時には「うーん全部TCP/IP経由かー」と思ったのだけど、この構造なら構成面の利便性がパフォーマンス差を上回りそうなので十分に納得いった。
3306あたりはiptablesで外向きを閉じておくかなーと思っていたのだけど、そもそもDockerホストの外部に対してポートを露出せずとも内部では通信できるという形なので、なかなか面白い。


ログは本番環境でも皆捨ててるのか(前述のRedmineでは、Redmine部分のログはVOLUMEで外部へ出せるようにしてた)、そもそもDockerベースのままで本番環境まで持っていかないのか、Docker Hubのどっかにはひたすらいろんなコンテナのログ出力部分をfluentdやらsyslog-ngやらへ流すようなDockerfile編集を行なってる職人がいるのか、全然分からなかったけれどこのへんは検討課題ということで。

現状のDockerfile+プリビルドされたコンテナをホストするDocker Hubによってユーザの手元に超手軽なパックとして実現(提供)されているものが
  • OSのバージョン固定
  • ミドルウェアのインストール
  • ミドルウェアの設定
  • ソフトウェアのインストール
  • ソフトウェアの設定
という「ready-to-start」な構成だとすると、
  • アクセス/オペレーションログ
  • ソフトウェア上で生成されたデータ(例えばWebコンソールから設定されてファイルに書きだされた設定情報、ユーザからアップロードされたデータやその他の経時生成されたデータ)
あたりを、場合によってはスナップショット込みでいい感じに制御して、あるホストが役目を終えようという時に他所のホストへと持って行きやすいようにする何か。
「大体の場合はこれに従っていればok」という感じのユニバーサルなんたらレイアウト的なサムシングがあるといいんだろうなーという小学生並みの感想を持った。
どういうものだろ。Dockerfile内でのVOLUME指定にカテゴリ(ログ、データ、設定など)を切っておいたうえで、ホスト上に展開する場合はホスト側からすぐに見える特定ディレクトリ以下にディレクトリを切って処理するとかかな。
こういう時にdocker exportしたら負けだと思ってる。

まあ初日だしね。最近の1.3とかのバージョンではいい感じにセマンティックになってるのかもしれない。
あと、コンテナリンクを含めてそれなりに複雑な構成を取ろうとすると、構成管理的な意味でChefとの関連というか連携があると概念的にはしっくり来るなーというのも感じた。こういう動きがChef Containerなんだろうか。出始めの時の記事を斜め読みした感じでは、Chef系で誰かがCook-bookをメンテする苦しみを味わってくれれば世の他の人は利益を享受できる格好だと認識してるのだけど、これをDockerでフリーダムなコンテナを作る系へと強引に接続してもあんまりうまく行くイメージがないので、きっと何か工夫があるんだろう。


さ、下回りの構成をいいかんじに現代化して試行錯誤しやすくなったところでアプリ作ろう。俺達のオープンデータ活用コンテストは、まだ始まったb(ry

0 件のコメント:

コメントを投稿