Dockerを使ってみての良い点と悪い点、及びディレクトリ構成

(注意 2014/11/13:この記事はいろいろと古いので注意してください)

さくらVPSをやめて公開してる物とかを全部自宅サーバーに戻すにあたって、いろいろな案があったが、結局自宅でいろんな用途に使っているサーバーにDockerを使って押し込めることにした。
それにあたってここしばらく作業をしてきて、Dockerの良い点と悪い点が分かってきたのでそれについて書く。
また、Dockerに移行するにあたって、実際に使う場合のディレクトリ構成について書いている人があまり居なくて戸惑ったのでそれについても書く。

Dockerとは

KVMなどと並べてLinuxの仮想化技術として取り上げられることが多く、最初何のことだかよく分かっていなかったが、chrootの超・強化版みたいなものである。(いろんな紹介のスライドに"chroot on steroids"とか書いてある)

良い点: VMとかではないので起動が早く軽い

chrootと違ってネットワークとかまで仮想化できる一方、KVMとかXenとかVirtualBoxみたいな完全仮想化ではないので、立ち上がりが早くてあまりメモリを食わない。

詳しくはここが分かりやすい。Docker: Linuxコンテナを使ってアプリケーションの配置を支援する

上を読んだ上で、公式サイトの内容に目を透してOnline Tutorial - Try It! | Dockerのinteractive tutorialとかをやれば最低限分かると思う。

悪い点: 普通の仮想環境とはだいぶ使い勝手が違う

chrootっぽいので、コンテナ内で動いてるプロセスが全部止まればコンテナも止まる。
コンテナはUbuntuなどをベースとして選べるが、完全に再現されている訳ではないので、例えばコンテナ内でデーモンを動かそうとdocker run peraudo/hoge sudo service *** startとかやっても動いてくれず止まってしまう。
大体のデーモンにはforegroundとかdaemon offとかそんなような名前のオプションがあって、それを設定ファイルとかで有効にしておけば、止まらないで動いてくれるので、docker run に-dオプションをつけるとそのまま背面で動いてくれる。

でも、それならどうやって複数のデーモンをコンテナ内で動かすのかという話になるが、supervisordを使うのがそれなりにベタだという事らしい。Using Supervisor - Docker Documentation

良い点: Dockerfile

DockerはImmutable InfrastructureとかBlue-Green Deploymentとかそんな感じの事をEC2のよな大げさなものを使わずとも楽にできるようにしてくれる道具である。今さら聞けない Immutable Infrastructure - 昼メシ物語
イメージの構築手順をDockerfileにスクリプトとして書いておけば、その都度設定済みのまっさらなサーバーの状態を再現できる。コンテナはその都度使い捨てできる。
例えば、何かをあれこれ設定をいじって試行錯誤して動くようにしたとして、Dockerを使わないでそんな事をやったとしたら、あっという間に再現不可能な設定の塊の完成である。

では、コンテナを使い捨てして、実際のImmutableにはできないデータなどはどうするかといえばVolumeといった機能を使うことで、ホストのディレクトリをコンテナ内のディレクトリにマッピングできるので、やっぱりコンテナは使い捨てできる。Managing data in containers - Docker Documentation

悪い点: セキュリティ

(注意 2014/11/13:現在のDockerは必ずしもLXCベースではない)

DockerのベースとなっているLXCあるいはLinux Containerという技術は、あくまで強化版chrootであってVMではないので、設定とかが不適切だと最悪ホストでコードを実行したりとかできてしまう。
DockerはたしかにLXCの便利なフロントエンドとして、デフォルトである程度適切な設定を提供してくれるし、
それについて、中の人が書いている Containers & Docker: How Secure Are They? | Docker Blog が、この文章は少々調子が良すぎるので注意である。

要約すると、「不適切なLXCの設定の元でコンテナ内でrootを掌握されると大変だけど、適切な設定で非rootでコンテナ内の物を動かせばまず安全!」といったような主張だが、まずいろんな人が書いてるDockerfileで、root以外でちゃんとデーモンとかを動かそうとしている物を見ない。setcapすれば非rootでもwell-known portsを開けられるとか書いてあるけどDockerのubuntuイメージにはsetcapは無い、さらにVolumeは必ず起動時点では所有者がrootになって、かといってchownするにはrootが必要だし、ともかくDockerでそういう事を考えるとハゲるという事に気がついたので、セキュリティについて考えるのはヤメにした。

およそホストで実行するのと同程度かそれよりはマシと見積もっておけば概ね間違いない筈である。

悪い点: 不安定

Docker自体ではなくLXCなのかもしれないが、枯れてるという前評判の割にはあまり枯れていないのか、慣れてきてイメージをビルドしまくっていたらカーネルパニック的なのを生やすことに3回ぐらい成功した。

使うならとりあえずカーネルのバージョンは上げておいたほうがいいと思う。

Ubuntuならdo-release-upgradeするとかで。

やはりこういう観点からいくと録画用サーバーと同居させるのは絶対間違ってる気がしたし他の人がやるならセキュリティ上からもKVMとか噛ませたほうがいいと思う。

ディレクトリ構成

  • ~/Docker
    • base
      • Dockerfile
      • build.sh
      • id_rsa.pub
      • sshd_config
    • main
      • Dockerfile
      • supervisord.conf
      • nginx.conf
      • build.sh
      • run.sh
    • schedulearn
      • Dockerfile
      • supervisord.conf
      • schedulearn
      • build.sh
      • run.sh

はじめはちょっと変わる度に全部一からビルドするのか…と思っていたが、baseにコンパイルが要りそうな物を全部ぶちこんで、他でFROMするようにしたらかなりストレスフリーになった。
あと、sshdを各コンテナの中で立ち上げるといろいろと見ることができてやりやすいという事で、一般的なようだ。(追記 2014/10/12:これは誤った例なので注意
If you run SSHD in your Docker containers, you're doing it wrong!

mainはnginxを静的コンテンツとschedulearnのリバースプロキシのために動かしている。
rootでsshログインするにはいろいろとsshd_configに書かなければいけなくてよくわからないけどStrictModesをはずしたとかそういう話はここでは省く。
あとDockerと関係ないけど手元から何も考えずにschedulearnの開発ディレクトリをコピったら.bundleのゴミデータのせいでトラブって時間を浪費した。

まとめ

公式サイトにもまだProductionでは使っちゃダメ!とか書いてあって、何度かクラッシュさせてその通りだと思ったし、かゆいところに手が届かないと感じる点も多かった。何よりかなり新しいソフトウエアで、schedulearnを作った頃にはまだ存在しなかった物である。日本語の資料もまだ少なくてどうやってもそれだけでうまくやるのは無理っぽいし、また、AUFSの制限でDockerfileのコマンド数に上限があったりとかいろいろとある。
しかし、Dockerを使わないで同等の事をするのはあまり考えたくないし、セキュリティ含め(中の人のブログに書いてあるように)今後かなり改善が図られると思うし、今後相当広く使われていくだろうという気がする。

追記(2014/7/31)

上ではコンテナの中でsshdを立てることを一般的と書いてあるが、Dockerの中の人によって明確に「誤り」だと言われているので注意すること。

Why you don't need to run SSHd in your Docker containers | Docker Blog