ようへいの日々精進XP

よかろうもん

Dockerfile の書き方「私的」なベストプラクティス(2)〜サービスの起動について〜

はじめに

Dockerfile を書く上で悩んでいるのが docker run -d ${container/image} でコンテナを走らせた際にコンテナ内にセットアップした Apache2 等のサービスを起動させる方法がズバリ解らない...のでとりあえず幾つかのサービスで試してみて起動方法の方向性みたいなものを模索してみたい。


参考


試したアプリケーション

docker コンテナで動かすことがあるかどうかは置いておいて、以下のようなアプリケーションで CMD 又は ENTRYPOINT を使って docker run -d を実行した際にアプリケーションが起動する方法を模索した。

  • OpenSSH
  • Apache2
  • Jenkins
  • td-agent
  • norikra

尚、アプリケーションは基本的に OS のパッケージからインストールした。コンテナの基となるイメージはこちらのイメージを使った。

OpenSSH

EXPOSE 22
CMD ["/usr/sbin/sshd","-D"]

こっちでもイケる。

EXPOSE 22
ENTRYPOINT ["/usr/sbin/sshd","-D"]

両方共にコンテナがデバッグモードで起動して ssh でアクセスすることが出来た。

Apache2

EXPOSE 80
env APACHE_RUN_USER    www-data
env APACHE_RUN_GROUP   www-data
env APACHE_PID_FILE    /var/run/apache2.pid
env APACHE_RUN_DIR     /var/run/apache2
env APACHE_LOCK_DIR    /var/lock/apache2
env APACHE_LOG_DIR     /var/log/apache2
env LANG               C
CMD ["/usr/sbin/apache2", "-D", "FOREGROUND"]

CMD ["/usr/sbin/apache2", "-D", "FOREGROUND"]ENTRYPOINT ["/usr/sbin/apache2", "-D", "FOREGROUND"] としてもイケた。両方ともに It works! が表示されるサイトにアクセス出来た。設定のキモは FOREGROUND のようです。

Jenkins

EXPOSE 8080
CMD ["/usr/bin/java","-jar","/usr/share/jenkins/jenkins.war"]

こっちでも...

EXPOSE 8080
ENTRYPOINT ["/usr/bin/java","-jar","/usr/share/jenkins/jenkins.war"]

こっちでも...イケた。但し、docker run -i -t ${images} /bin/bash で起動した際に少し挙動が異なるので注意する。

CMDJenkins の起動を指定した場合。

$ docker run -i -t inokappa/jenkins-test /bin/bash
root@1ec10ea2b0de:/# 

上記のように /bin/bashCMD が上書きされた形となり Jenkins は起動していないがコンソールにアクセスし操作が可能となる。対して、ENTRYPOINTJenkins の起動を指定した場合。

$ sudo docker run -i -t inokappa/jenkins-test /bin/bash
Running from: /usr/share/jenkins/jenkins.war
webroot: $user.home/.jenkins
Dec 28, 2013 6:53:14 PM org.eclipse.jetty.util.log.JavaUtilLog info
INFO: jetty-8.y.z-SNAPSHOT
Dec 28, 2013 6:53:14 PM org.eclipse.jetty.util.log.JavaUtilLog info
INFO: Extract jar:file:/bin/bash!/ to /tmp/jetty-0.0.0.0-8080-bash--any-/webapp
Dec 28, 2013 6:53:14 PM org.eclipse.jetty.util.log.JavaUtilLog info
INFO: NO JSP Support for , did not find org.apache.jasper.servlet.JspServlet
Dec 28, 2013 6:53:14 PM org.eclipse.jetty.util.log.JavaUtilLog info
INFO: Started SelectChannelConnector@0.0.0.0:8080
Dec 28, 2013 6:53:14 PM winstone.Logger logInternal
INFO: Winstone Servlet Engine v2.0 running: controlPort=disabled


^CDec 28, 2013 6:53:37 PM winstone.Logger logInternal #=> Ctrl +c で終了させる
INFO: JVM is terminating. Shutting down Winstone

上記のように ENTRYPOINT でサービスを上げた場合にはコンソールにアクセスしてもフォアグランドで Jenkins が動作してしまっている為にコンソールでの操作が限られてしまう。

td-agent

EXPOSE 24224
CMD ["/usr/lib/fluent/ruby/bin/ruby", "/usr/sbin/td-agent", "-c", "/etc/td-agent/td-agent.conf", "--log", "/var/log/td-agent/td-agent.log"]

こっちでも...

EXPOSE 24224
ENTRYPOINT ["/usr/lib/fluent/ruby/bin/ruby", "/usr/sbin/td-agent", "-c", "/etc/td-agent/td-agent.conf", "--log", "/var/log/td-agent/td-agent.log"]

こっちでも...イケた。

norikra

もともと norikra の検証環境を作る目的で Dockerfile を弄り始めたのがきっかけ。

EXPOSE 26571                                        
EXPOSE 26578                                        
CMD ["/usr/local/jruby/bin/norikra", "start"]      

CMDENTRYPOINT どっちでもイケる。

最後に

  • CMDENTRYPOINT の使い分けがますます解らなくなってきた...けど
  • CMDENTRYPOINT を使い分けるなら docker run でコンテナにログインする必要があるか否か(docker run -i -t ${container} /bin/bash するかしないか)で使い分けるのも一案かも
  • ま、だけどサービスの起動についてだいだい整理出来たような気がする
  • 検証に使った Dockerfileこちら