🐳
docker でフォアグラウンド実行できないサービスを supervisord で管理できるようにする
はじめに
docker 初心者向けではない(ような気がする)ので悪しからず。困っている人に向けて書きました。
というかこんなタイトルにしてますけど、結局 docker で service コマンドを使って、うまくプロセスを管理したい!ってことです。
前提
- docker では常にプロセスがフォアグラウンドで動いていないと、docker のコンテナが終了してしまって、大変切ない思いをします。
- なので、docker を使っている人たちはどうにかしてフォアグラウンドで動かすように頑張っている(ように見えます)
- 例えば、apache なら sudo /usr/sbin/apache2 -DFOREGROUND みたいな感じ。
- 「複数のプロセスを動かそう」 と思った時には supervisord というものを使い始めて、更に面倒なことに。
- しかし、やっぱり service コマンドとか便利なものがあるんだから、そこは docker コンテナ上でも使っていって、supervisord で管理できるようにしようよ、ということで書きました。
こうすることで嬉しい事
- いちいち各デーモンプログラムがフォアグラウンド対応かを気にしなくてよくなります。
- 統一した方法でサービスの管理ができるようになります(スクリプトをいちいち書くのが面倒な人は向いてませんが)
- supervisorctl コマンド経由のステータス参照が正しく見えて、なんとなく「俺やってる」感が出せます
答え
- 無粋なようですが、先に答えを。
- シェルスクリプトで service コマンドを実行して、あとは supervisord 経由で「しっかり(start も stop も)管理できるようにしようじゃないか、という戦略です。
- supervisord に、このスクリプトを登録してあげると、いい感じに supervisorctl コマンド経由でコントロールできるようになります。
- apache2 の例だとこうなります。
#!/bin/sh
SERVICE_NAME=apache2
service ${SERVICE_NAME} start
stop() {
service ${SERVICE_NAME} stop
}
reload() {
service ${SERVICE_NAME} reload
}
int() {
service ${SERVICE_NAME} stop
exit 1
}
trap stop TERM
trap reload HUP
trap int INT
while :
do
sleep 5
service ${SERVICE_NAME} status
if [ "X$?" != "X0" ]; then
exit 1
fi
done
やってること
- まったく難しくはなくて、ただ単に trap コマンドを使って終了ステータスを見てあげているだけです。
- あとは while のループをしていますが、一応 CPU に優しくしてあげるために 5秒間隔でステータスを見ています。
- service hogehoge status は生きていれば exit status($?)は 0 なので、突発的にデーモンが死んだ場合でも、supervisorctl から補足できます。
実験
スタートしてみる
# まずはステータスをみる
root@7979e0ff08a2:/# sudo supervisorctl status
apache2 STOPPED Nov 14 01:31 PM
sshd RUNNING pid 24, uptime 0:00:27
# 開始
root@7979e0ff08a2:/# sudo supervisorctl start apache2
apache2: started
# 無事起動したか確認
root@7979e0ff08a2:/# sudo supervisorctl status
apache2 RUNNING pid 166, uptime 0:00:14
sshd RUNNING pid 24, uptime 0:01:21
# 本当に起動したか確認
root@7979e0ff08a2:/# ps axuwww
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 18180 2004 ? Ss 13:31 0:00 /bin/bash
root 23 0.0 0.5 52116 12236 ? Ss 13:31 0:00 /usr/bin/python /usr/bin/supervisord -c /etc/supervisor/supervisord.conf
root 24 0.0 0.1 61364 3036 ? S 13:31 0:00 /usr/sbin/sshd -D
root 166 0.0 0.0 4444 648 ? S 13:32 0:00 /bin/sh /docker_scripts/apache_run.sh
root 183 0.0 0.1 71300 2576 ? Ss 13:32 0:00 /usr/sbin/apache2 -k start
www-data 186 0.0 0.2 360464 4252 ? Sl 13:32 0:00 /usr/sbin/apache2 -k start
www-data 187 0.0 0.2 360464 4248 ? Sl 13:32 0:00 /usr/sbin/apache2 -k start
root 274 0.0 0.0 4344 364 ? S 13:33 0:00 sleep 5
root 275 0.0 0.0 15568 1100 ? R+ 13:33 0:00 ps axuwww
それっぽく動いてますね。
ストップしてみる
- じゃぁ、ある意味メインの stop 処理です。
# まずは RUNNING になっていることの確認
root@7979e0ff08a2:/# sudo supervisorctl status
apache2 RUNNING pid 166, uptime 0:02:13
sshd RUNNING pid 24, uptime 0:03:20
# ストップしてみる
root@7979e0ff08a2:/# sudo supervisorctl stop apache2
apache2: stopped
# ストップしているようだ
root@7979e0ff08a2:/# sudo supervisorctl status
apache2 STOPPED Nov 14 01:35 PM
sshd RUNNING pid 24, uptime 0:03:37
# 本当にプロセスが死んでくれているか確認
root@7979e0ff08a2:/# ps axuwww
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 18184 2008 ? Ss 13:31 0:00 /bin/bash
root 23 0.0 0.5 52364 12288 ? Ss 13:31 0:00 /usr/bin/python /usr/bin/supervisord -c /etc/supervisor/supervisord.conf
root 24 0.0 0.1 61364 3036 ? S 13:31 0:00 /usr/sbin/sshd -D
root 537 0.0 0.0 15568 1088 ? R+ 13:35 0:00 ps axuwww
最後に
- シェルスクリプトもこんな感じで書けば、結構それっぽく動いてくれることがわかりました。
- supervisord で管理するときに「(このプロセス)フォアグラウンドで動かせるかなー・・・」というのを気にしなくて良くなるのは、いいことだと思います。
Discussion