Dockerで複数デーモンを起動する手法をまとめてみる

f712a111e120c65ed3ec259a3f9c812b_s

この話、 「Dockerでsupervisordを使わずに複数デーモンを起動する方法」 でも書いてるんだけど、調べたらほかにもいろいろ試行錯誤している人がいるので、網羅的にまとめなおしてみた。

ご存知のとおり、Dockerはコンテナ(仮想インスタンス)を立ち上げたあと、単一のフォアグラウンドプロセスを動かし続けないと自然終了してしまう。言い方に語弊があるかもしれないけど、簡単に言うと「デーモンをいくつも起動して、はい使おう」というわけにはいかないっつーことだ。

とはいえ、

  • じゃあデーモンとして動作するのが前提になってるアプリケーションはどうすりゃええねん
  • 「postfixだけ」とか「MySQLだけ」とか二つ以上のデーモンを動作させたいときは?

ということで 複数デーモンを起動しっぱなしにする方法 を追求しないといけない。

ここでは、複雑な順・個人的にはあまり好きじゃない順に流す。

Supervisor を使う

「Supervisor」 は、複数のプログラムを実行して常駐させておくことができるプロセス管理ツールだ。古株の人はdameontoolsとかの親戚だと思えばいい。

iniファイル形式で起動したいプログラムを記述して、DockerfileのCMDでsupervisorを起動すれば複数デーモンを起動しっぱなしにできる。が、個人的にめんどくさい理由として、

  • プログラムをフォアグラウンドで動くように指定しないといけない。たとえばApacheなら
    /usr/sbin/httpd -DFOREGROUND
    なんだけど、こういうのいちいち調べるのが面倒。実質的に存在しないものもある
  • Pythonist以外の人には Supervisor自体のインストールが面倒…。
    Supervisor はPythonで書かれている。
    宗教論争になりそうだけど、Pythonで書かれたツールのインストールは
    setuptools とか pip とか出てきてよくわからん…。
    まあ、yum -y install python-setuptools && easy_install supervisor すれば
    いいだけなんだけど…

ということで、最初はぼくも使ったけどパス。

monit を使う

「monit」 は(も?)、本来はプロセス監視ツール。
インストールが簡単なわりにできることが多くて、個人的には重宝してる。

やることはSupervisorと同じで、設定ファイルに監視対象のデーモンを書いて、
monit自体をフォアグラウンド起動させれば複数のデーモンを起動しっぱなしにできる。

start program = "/sbin/service sshd start"

みたいに、サービススクリプト(はsystemd時代でもう古いけど)を呼び出すだけ
ですむのが Supervisor よりラクなとこ。デメリットは…

  • もともと死活監視とか負荷計測とかするツールなので…なんかこう…
    こういう用途に使うともやもやする

だけかな。早い話が趣味に合わないです。すみません。

tail -f を使う

コロンブスの卵的発想。

# tail -f /var/log/messages

ってやると、tailが立ち上がりっぱなしでログの追記を監視するけど、
これの応用で、

# tail -f /dev/null

すればフォアグラウンドのまま帰ってこないじゃん! という手法です。

具体的には

CMD /sbin/service httpd start && /bin/tail -f /dev/null

みたいな感じにするんだと思いました(ググるのがめんどくさいので
適当に書いてます)。

…たしかに動くので、ちょっとしたテストのときはいいと思うんだけど(Dockerfile
じゃなくて docker run に実行コマンドを与えるときとかラクだと思う)、
いかんせん、初めて見た人に「これなにやってんの?」っていうのが
わかりにくいのがキツいかと。

起動サービスをスクリプトにまとめて最後に永久sleep

で、最終的にぼくが落ち着いたのがこの方法。

とにかく起動したいデーモンをserviceコマンドで呼び出しまくったあと、
永久に sleep するというシェルスクリプトを書く。

#!/bin/bash
/sbin/service crond start
/sbin/service postfix start
/sbin/service httpd start

while true
do
    sleep 10
done

/etc/services.sh とかいう名前でイメージ内に置いて、
Dockerfile の最後で

ENTRYPOINT /etc/services.sh

とやれば並べたデーモンが動きっぱなしになる、と。

個人的にはこれがいちばんスッキリする。
ちなみに sleep の無限ループがイヤな人は tail -f /dev/null してもいいと思う。

ということでいろんなやり方があるなー、てな感じでした。
そんじゃーね!