Docker視点で見るSupervisorの使い方

Docker初心者なので、Dockerを活用する上でのSupervisorの使い方, Tipsをチラ裏しておきます。

#そもそもSupervisorとは
[この記事](http://qiita.com/yushin/items/15f4f90c5663710dbd56)とかが参考になりますが、そもそもはプロセスの管理、Daemon化、永続化(プロセスが不正終了したら自動で再起動など)のTool、と言うイメージです。

Docker視点で見ると、『Docker Container上ではProcessがForegroundで動いていないとContainerは終了する』というContainerの制限がある中で、1つのContainer上で複数のプロセス (例えば`Node + Mongo`や`Fluentd + Elasticsearch`など)を動かしたい、永続化させたい時にこのSupervisorというToolが使われます。

supervisord.confのOptionは、[公式ページ](http://supervisord.org/configuration.html)を見て下さい。

#基本的な使い方
nginxをsupervisor上で動かしたい、というCase Studyの場合、Dockerfileは以下の様になります。

```
FROM ubuntu:14.04

#Install nginx
RUN apt-get update && apt-get -y install nginx curl
RUN echo "daemon off;" >> /etc/nginx/nginx.conf

#Install Supervisor and config
RUN apt-get install -y supervisor
RUN touch /etc/supervisord.conf
RUN echo '[supervisord]'  >> /etc/supervisord.conf
RUN echo 'nodaemon=true'  >> /etc/supervisord.conf
RUN echo '[program:nginx]' >> /etc/supervisord.conf
RUN echo 'command=nginx'   >> /etc/supervisord.conf

EXPOSE 80
CMD /usr/bin/supervisord -c /etc/supervisord.conf
```

`[supervisord]`と`nodaemon=true`の行は必須で、`nodaemon=true`でsupervisor自体がforegroundプロセスとして振る舞いDocker containerの終了を防ぐ役割を果たします。`command=`には、Container上でnginxを単体で動かし続ける場合に書いておくべきcommandを書いておく必要があります。

Dockerfileは簡潔に記載してConfig fileは別fileが良い、と言う方は、supervisord.confというfileに以下の内容を書いて置いて、`/etc/`以下に配置するようにDockerfile側に記載しておけばOKです。

```
[supervisord]
nodaemon=true

[program:nginx]
command=nginx
```




#複数のプロセスを動かす場合の使い方
Elasticsearch + Fluentdをsupervisor上で動かしたい、というCase Studyの場合、Dockerfileは以下の様になります。

```
FROM ubuntu:14.04
RUN apt-get update -y

#Install Elasticsearch
ENV ELASTICSEARCH_VERSION elasticsearch-1.4.4
RUN apt-get install -y curl openjdk-7-jdk
RUN mkdir /opt/elasticsearch
RUN curl -sL "https://download.elasticsearch.org/elasticsearch/elasticsearch/${ELASTICSEARCH_VERSION}.tar.gz" | tar xz -C /opt/elasticsearch --strip=1

#Install Fluentd and plugins
RUN apt-get install -y libcurl4-openssl-dev git-core build-essential ruby-dev
RUN curl -L http://toolbelt.treasuredata.com/sh/install-ubuntu-trusty-td-agent2.sh | sh
COPY td-agent.conf /etc/td-agent/td-agent.conf
RUN ulimit -n 65536

#Install Supervisor and config
RUN apt-get install -y supervisor
RUN touch /etc/supervisord.conf
RUN echo '[supervisord]'  >> /etc/supervisord.conf
RUN echo 'nodaemon=true'  >> /etc/supervisord.conf
RUN echo '[program:elasticsearch]'             >> /etc/supervisord.conf
RUN echo 'command=/opt/elasticsearch/bin/elasticsearch' >> /etc/supervisord.conf
RUN echo '[program:td-agent]'             >> /etc/supervisord.conf
RUN echo 'command=/usr/sbin/td-agent' >> /etc/supervisord.conf

# expose port for elasticsearch
EXPOSE 9200

# expose port for fluentd
EXPOSE 24224

CMD /usr/bin/supervisord -c /etc/supervisord.conf
```

#Supervisorで気をつけるべき設定
###各プロセスの標準出力について
Supervisorは __Default設定では__ 、各プロセスからの標準出力を受け取りfileに書き出す設定になっています。そのため、Supervisorを経由して各プロセスを動かす場合に、各プロセスの標準出力の内容を見る事が出来ません。

fileではなく標準出力に書き出したい場合は、`stdout_logfile`を`/dev/fd/1`に設定してあげると良いです。たとえば、以下のように設定すると、td-agentのプロセスから出た標準出力は、(Supervisorを経由して)システム全体の標準出力にRouteされます。

```
[supervisord]
nodaemon=true

[program:elasticsearch]
command=/opt/elasticsearch/bin/elasticsearch

[program:td-agent]
command=/usr/sbin/td-agent
stdout_logfile=/dev/fd/1
stdout_logfile_maxbytes=0
```