ようへいの日々精進XP

よかろうもん

Dockerfile の書き方「私的」なベストプラクティス(3)〜サービスの起動について〜

はじめに

  • ずるずる引きずってすいません
  • Dockerfile 内でのアプリケーションサービスについて monit を利用する方法を思いついたので試してみたのでまとめてみた

参考


どうするのか?

何はともあれ monit をインストールする。

sudo apt-get install monit

Dockerfile 内では以下のように書く。

RUN apt-get install monit

ちなみに monit の詳細については上記の公式サイトへ。monit をざっくり言うと...

  • ホスト上で稼働しているサービスを監視する
  • 監視しているサービスが停止した場合にはルールに従ってサービスのプロセスを再起動する
  • サービスの監視方法としては PID ファイルの監視やプロセス名を監視する
  • WebUI が利用可能で WebUI から監視しているプロセスの再起動や稼働状況を監視出来る

イメージ

やってることは簡単で以下のようなイメージ。

f:id:inokara:20140104071534p:plain

試しに...

以下のサービスを docker run -d 実行時に起動したい場合...

  • nginx
  • td-agent
  • norikra

コンテナ内で起動したいサービスの数だけ monit 用の設定を下記のように記載して /etc/monit/conf.d 以下に放り込む。

nginx

/etc/monit/conf.d/nginx.conf というファイル名で保存する。(ファイル名は任意)

check process nginx with pidfile /var/run/nginx.pid
    start program = "/etc/init.d/nginx start"
    stop  program = "/etc/init.d/nginx stop"

ちなみに nginx を起動する際に daemon off; をつけることでフォアグランドでの起動が可能になる。但し、その場合にはログのローテーション等について別途検討する必要があるようだ。

td-agent

/etc/monit/conf.d/td-agent.conf というファイル名で保存する。(ファイル名は任意)

check process td-agent with pidfile /var/run/td-agent/td-agent.pid
    start program = "/etc/init.d/td-agent start"
    stop program = "/etc/init.d/td-agent stop"

td-agent ではなく fluentd に応用出来る。但し、pid ファイルのパス等には注意する。

norikra

/etc/monit/conf.d/norikra.conf というファイル名で保存する。(ファイル名は任意)

check process norikra with pidfile /var/run/norikra/norikra.pid
    start program = "/usr/local/bin/norikractl start"
    stop  program = "/usr/local/bin/norikractl stop"

上記の /usr/local/bin/norikractl は以下のようなシェルスクリプトこちらを参考に自作した。(monit だけで PATH の上書き方法が解らなかったので...)

#!/bin/bash

export PATH=$PATH:/usr/local/jruby/bin

if [ ! -d /var/run/norikra ];then
  mkdir /var/run/norikra
else
  echo ""
fi

case $1 in
   start)
      /usr/local/jruby/bin/norikra start &
      sleep 3
      ps ax | grep  \[j\]ava | awk '{print $1}' > /var/run/norikra/norikra.pid;
      ;;
    stop)
      kill `cat /var/run/norikra/norikra.pid` ;;
    *)
      echo "usage: norikractl {start|stop}" ;;
esac
exit 0

Dockefile への組み込み

上記の /etc/monit/conf.d/*.conf ファイルに関して Dockerfile を使ってコンテナに組み込む為には ADD コマンドを利用して docker build 時に組み込むようにする。以下のように記載する。

ADD td-agent.conf /etc/monit/conf.d/td-agent.conf
ADD nginx.conf /etc/monit/conf.d/nginx.conf
ADD norikra.conf /etc/monit/conf.d/norikra.conf

上記で Dockerfile と同じディレクトリに置かれた td-agent.confnginx.confnorikra.conf がコンテナ内の所定のパスにアップロードされる。そして、Dockerfile の最後で以下のように EXPOSE でサービスに必要なポートを開放して monitCMD コマンドで起動している。

# for norikra
EXPOSE 26571
EXPOSE 26578
# for fluentd
EXPOSE 24220
EXPOSE 24224
# for nginx
EXPOSE 80
# for ssh
EXPOSE 22
# for monit
EXPOSE 2812
CMD ["/usr/bin/monit", "-I", "-c", "/etc/monit/monitrc"]

尚、monit を起動する際には -I オプションをつけることでフォアグランドで起動させることで docker run -d しても exit 0 でコンテナがデタッチで起動せずに終了してしまうことを避けることが出来る。また、全てのアプリケーションが monit を介して起動する為、monit が起動すると全てのアプリケーションが起動することになる。(やった!)

monit で稼働プロセスの管理

monit では WebUI で monit で管理しているプロセスを確認、操作等を行うことが出来る。monitrc で以下の設定を行うことで WebUI を利用することが出来る。(※実際に運用環境で利用する場合にはアクセス元の制限やログイン名パスワードの管理はちゃんとすること。)

set httpd port 2812 and
  use address 0.0.0.0 # 全てのホストからの接続を受け付ける
  allow admin:monit  # ログイン名、パスワードを指定

monit を起動してブラウザで http://${container_IP}:2812/ にアクセスすると以下のように表示される。

f:id:inokara:20131229211842p:plain

各プロセス名のリンクをクリックすると詳細情報が表示される。また、適切に権限が設定されている場合には詳細情報のページからプロセスの起動、停止を行うことも出来る。


最後に

  • Dockerfile だけでコンテナ内で稼働させるサービスを制御するのは個人的には限界を感じた(三回程記事を書く為に検証した結果)
  • monit を使うことで個々のサービスの起動や停止、プロセスの監視を抽象化して一元管理することが出来るのでコンテナ内で稼働させるサービスの制御はこのようなツールに任せた方が幸せになれそうな気がする
  • dockerDockerfile を使えば簡単にアプリケーションコンテナを構築、提供することが出来るし、手軽にそのインフラを構築することが出来る
  • コンテナ内で稼働する各種サービスは monit を使って管理すれば小難しいコマンドラインでの管理を極力減らせることが出来る
  • まだまだサービスの実運用で利用するには検証は必要かなーと思うけど、インフラ運用の新しい方向性(コンテナを量産して必要に応じて使い捨てる)を見いだせたような気がする(大げさ)