第16回 1つのDockerコンテナでサービスをたくさん動かすには?(応用編)古賀政純の「攻めのITのためのDocker塾」(1/3 ページ)

Dockerコンテナで複数のサービスを動かすポイントを解説しましたが、今回はその応用編として具体的に3つの方法をご紹介します。

» 2016年02月17日 08時00分 公開

 コンテナで複数のサービスをで起動させるにはどうすればよいのでしょうか。前回は基本的な注意点などを解説しましたが、今回は比較的簡単な方法を3つご紹介します。

 まず、コミュニティの間では「そもそもDockerコンテナで同時に稼働させるアプリケーションの数を幾つにすべきか」という議論があります。1つのコンテナに1つのアプリケーションを稼働させるようにすれば、複数のコンテナが連携して稼働する場合でも、コンテナを組み合わせて汎用的に使える割合が高くなります。だからといって、稼働するアプリケーションが多いシステムでは、1コンテナ・1アプリケーションのポリシーを厳密に適用してしまうと、コンテナの数が膨大になることが予想されます。

 現実的に考えると、1つのコンテナにおいても、多少の汎用性を犠牲にしても複数のアプリケーションを稼働させるといった運用が十分に考えられます。この場合、1つのコンテナで複数のサービスを同時稼働させる仕組みが必要です。例えば、1つのコンテナでWebサービスとFTPサービスを同時に提供するような場合、httpdデーモンとvsftpdデーモンの2つを起動させる必要があります。

複数のサービスを起動させる方法・ラッパースクリプト

 それではWebサービスとFTPサービスを同時に稼働させる場合、どのようなDockerfileになるのでしょうか。以下の例を見てください。


# mkdir /root/apache_ftp
# cd /root/apache_ftp
# vi Dockerfile
FROM centos:centos7.2.1511
MAINTAINER Masazumi Koga
ENV container docker
ENV http_proxy http://proxy.yoursite.com:8080
ENV https_proxy http://proxy.yoursite.com:8080
RUN yum update -y && yum clean all
RUN yum install -y iproute httpd vsftpd && yum clean all
RUN echo "Hello Apache." > /var/www/html/test1.html
RUN echo "Hello Vsftpd." > /var/ftp/pub/test2.txt
COPY myapp.sh  /usr/local/bin
RUN  chmod 755 /usr/local/bin/myapp.sh
EXPOSE 80
ENTRYPOINT ["/usr/local/bin/myapp.sh"]

 このDockerfileには、httpdデーモンとvsftpdデーモンの2つをインストールしています。今回、httpdによって提供するWebコンテンツは「/var/www/html/test1.html」、vsftpdによって提供するファイルは「/var/ftp/pub/test2.txt」としました。しかしDockerfileを見渡しても、httpdデーモンとvsftpdデーモンを直接起動する処理がありません。その代わりENTRYPOINTには、なにやらmyapp.shという謎のスクリプトが指定されています。myapp.shスクリプトは一体何者なのでしょうか。このmyapp.shは、httpdデーモンとvsftpdデーモンを稼働させるスクリプトです。今回はmyapp.shを以下のように作成しました。


# cat myapp.sh
#!/bin/sh
/usr/sbin/httpd -k start				←httpdデーモンを起動
/usr/sbin/vsftpd /etc/vsftpd/vsftpd.conf		←vsftpdデーモンを起動
tail -f /dev/null					←永久に終わらないtailコマンド

 myapp.shスクリプト内において、httpdデーモンとvsftpdデーモンはバックグラウンドで起動するように記述されています。しかし、バックグラウンドで起動したプロセスのみでは、コンテナがすぐに終了してしまうため、コンテナを稼働し続ける仕組みを提供する「tail -f /dev/null」が組み込まれています。このtailコマンドの活用は連載の第9回でも紹介しましたが、プロセスがすぐに終了するようなコマンドだけではなく、バックグラウンドで稼働するデーモンが複数存在する場合にも有用です。実際にDockerfileが存在するディレクトリにmyapp.shスクリプトを用意し、Dockerイメージのビルドおよびコンテナの起動を行ってみてください。


# docker build -f ./Dockerfile -t centos:c7apache02 --no-cache=false .
# docker run -itd --name web0002 centos:c7apache02

 起動したコンテナにおいて稼働しているプロセスをホストOSから確認してみます。


# docker exec -it web0002 ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 12:09 ?        00:00:00 /bin/sh /usr/local/bin/myapp.sh
root         7     1  0 12:10 ?        00:00:00 /usr/sbin/httpd -k start
apache       9     7  0 12:10 ?        00:00:00 /usr/sbin/httpd -k start
apache      10     7  0 12:10 ?        00:00:00 /usr/sbin/httpd -k start
apache      11     7  0 12:10 ?        00:00:00 /usr/sbin/httpd -k start
apache      12     7  0 12:10 ?        00:00:00 /usr/sbin/httpd -k start
apache      13     7  0 12:10 ?        00:00:00 /usr/sbin/httpd -k start
root        14     1  0 12:10 ?        00:00:00 /usr/sbin/vsftpd /etc/vsftpd/vsftpd.conf
root        15     1  0 12:10 ?        00:00:00 tail -f /dev/null
root        20     0  0 12:14 ?        00:00:00 ps -ef

 コンテナ内で実行されたmyapp.shスクリプトにおいて、永久に処理が終わらないtailコマンドが組み込まれていることにより、myapp.sh内で起動したhttpd、vsftpdが稼働し続けていることが分かります。しかしこの場合は、起動したいサービス以外にmyapp.shのようなカスタムの起動スクリプトを別途作成しなければなりません。この例のmyapp.shは非常に単純ですが、稼働させるアプリケーションが多岐にわたる場合や、挙動を変えるための起動オプションの変更などを細かく定義する必要がある場合は、それらを正確に処理できるmyapp.shスクリプトを用意しなければならず、アプリケーション以外にスクリプトもメンテナンスしなければなりません。

 サービスを起動・停止させるためのスクリプトは、一般的に「ラッパースクリプト」と呼ばれますが、このラッパースクリプトはDockerの世界だけではなく、古くから高可用性クラスタ環境におけるサービスの起動・停止にも使われています。しかし、ラッパースクリプト自体が肥大化し、複雑になることが多く、バイナリのオプションの仕様変更やラッパースクリプトの改変の度に十分なテストを行う必要があります。

図:ラッパースクリプトを使った回避策
       1|2|3 次のページへ

Copyright © ITmedia, Inc. All Rights Reserved.

注目のテーマ