めもめも

このブログに記載の内容は個人の見解であり、必ずしも所属組織の立場、戦略、意見を代表するものではありません。

Dockerコンテナー内のbashからアプリケーション停止処理を実施するTIPS

Dockerのコンテナーでアプリケーションを起動する場合、専用の起動スクリプトからアプリケーションを起動して、最後に(後からdocker attachできるように)bashを起動しておくことがあります。

次は、httpdサービスを起動するコンテナーを作成する簡単なDockerfileですが、コンテナー起動時にスクリプト「init.sh」を実行するようにしています。

Dockerfile

FROM centos:centos6
MAINTAINER enakai

RUN yum -y install httpd

ADD src /var/www/html
RUN chmod -R 644 /var/www/html/*

ADD init.sh /usr/local/bin/init.sh
RUN chmod u+x /usr/local/bin/init.sh
CMD ["/usr/local/bin/init.sh"]

一方、スクリプトの中身はこんな感じ。

init.sh

#!/bin/sh

service httpd start

/bin/bash

しかしながら、この方法の場合、「docker stop」でコンテナーを停止した際にhttpdサービスをきれいに停止した上で、コンテナーを停止するということができません。「docker stop」は、「CMD」で起動した最初のプロセス(この例では「init.sh」)に対して、TERMシグナルを投げた後、その他のプロセスは強制停止してしまいます。「docker stop」の際に、「service httpd stop」を自動実行することはできないのでしょうか?

これは、次の方法で実現できます。先ほどの「init.sh」を次の内容に入れ替えます。

init.sh

#!/bin/sh

service httpd start

cat <<EOF >>~/.bashrc
trap 'service httpd stop; exit 0' TERM
EOF
exec /bin/bash

これは、execコマンドでbashを起動することにより、init.shのプロセスをbashに入れ替えています。これにより、bashがTERMシグナルを受けるようになります。さらに、.bashrcにtrapコマンドを仕込むことで、TERMシグナルのハンドラーを設定しています。これで、TERMシグナルを受けたbashは、「service httpd stop」でhttpdサービスを停止した後に終了してくれます。

ばっちぐー。