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サービスを停止した後に終了してくれます。
ばっちぐー。