🐳

docker でフォアグラウンド実行できないサービスを supervisord で管理できるようにする

2020/10/02に公開

はじめに

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