Supervisord を使って Docker コンテナ内に複数プロセスを起動する
Docker コンテナでは通常ひとつのプロセスしか起動できない。 コンテナ仮想化技術ではプロセスをシステムから隔離することで仮想化を実現している (隔離されたプロセス = コンテナ) ため、エントリポイントとなるプロセスがひとつになってしまう。 そのため、各サービスを直接起動しようとする限り Apache httpd を動かしながら MySQL を起動するといったことができない。 しかし、エントリポイントのプロセスがひとつであったとしても、そこからプロセスをコンテナ内で fork させる分には問題がない。 つまり、最初のプロセスが複数のプロセスに fork した上でお目当てのサービスを起動してくれれば良い。 Supervisord は正に上記の動作をしてくれるパッケージだ。 今回は Supervisord を使って Apache httpd と MariaDB が動作する Docker イメージを作ってみる。
まずは Supervisord の設定ファイルを用意する。 Supervisord が各サービスを起動するためのコマンドを記述しておく。
$ cat << EOF > supervisord.conf [supervisord] nodaemon=true [program:httpd] command=/usr/sbin/httpd -D FOREGROUND [program:mariadb] command=/usr/bin/mysqld_safe --skip-grant-tables EOF
Apache httpd がトップページで表示する Web ページも用意しておく。
$ cat << EOF > index.html Hello, World!! EOF
Docker イメージをビルドするための Dockerfile は以下の通り。 Apache httpd と MariaDB を起動できる状態まで持っていった上で Supervisord を起動するように作る。 ベースのイメージには CentOS7 を使った。
$ cat << EOF > Dockerfile FROM centos:centos7 MAINTAINER example <[email protected]> # Supervisord の設定ファイルを Docker イメージ内に転送する ADD supervisord.conf /etc/supervisord.conf # Apache httpd でトップページに表示する Web ページを Docker イメージ内に転送する ADD index.html /var/www/html/ # python-pip をインストールするために EPEL を入れておく RUN yum -y install epel-release # 必要なパッケージをインストールする RUN yum -y install httpd mariadb-server python-pip # PIP で Supervisord をインストールする RUN pip install supervisor # Apache httpd と MariaDB が使うポートを外部に公開する EXPOSE 80 3306 # Supervisord を起動する CMD ["/usr/bin/supervisord"] EOF
$ docker build -t example/supervisord . ...(省略)... Successfully built b339c247b40d
作成した Docker イメージを元にコンテナを起動する。 Apache httpd (80) と MariaDB (3306) が使うポートを外部に開放するのを忘れない。
$ docker run -p 3306:3306 -p 8080:80 example/supervisord 2015-06-28 19:43:11,027 INFO success: httpd entered RUNNING state, process has stayed up for > than 1 seconds (startsecs) 2015-06-28 19:43:11,027 INFO success: mariadb entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
別のターミナルからコンテナに接続してみる。 今回は boot2docker を使っているのでコンテナを動作させている Docker ホストの IP アドレスを boot2docker ip コマンドで取得している。 Docker デーモンがローカルで動作している場合には localhsot で構わない。
$ wget -qO - http://$(boot2docker ip):8080/ Hello, World!! $ mysql -u root -h $(boot2docker ip) -e "show databases;" +--------------------+ | Database | +--------------------+ | information_schema | +--------------------+