Dockerのログまわりのドキュメントを読んでいて、ちょっと気になったところがありまして。
View logs for a container or service | Docker Documentation
The official nginx image creates a symbolic link from /var/log/nginx/access.log to /dev/stdout, and creates another symbolic link from /var/log/nginx/error.log to /dev/stderr, overwriting the log files and causing logs to be sent to the relevant special device instead. See the Dockerfile.
「docker container logs」で表示可能にできるようなコンテナ上で動作するプロセスが出力する内容は、標準出力、または
標準エラー出力にその内容を書き出す必要があります。
このため、たとえばApacheのオフィシャルイメージの場合、Apacheのプロセスをフォアグラウンドで実行するようにして
回避しています。
CMD ["httpd-foreground"]
exec httpd -DFOREGROUND
Nginxの場合はこのような回避策がないため、アクセスログおよびエラーログのファイルを、それぞれ標準出力(/dev/stdout)、
標準エラー出力(/dev/stderr)のシンボリックリンクとして作成することで、回避しているようです。
# forward request and error logs to docker log collector RUN ln -sf /dev/stdout /var/log/nginx/access.log \ && ln -sf /dev/stderr /var/log/nginx/error.log
なるほど、覚えておきましょう。
というわけで、ちょっと試してみます。
Apache Tomcatを題材にして、こんなDockerfileを用意。
Dockerfile
FROM openjdk:8 RUN apt-get update -y && \ apt-get install -y wget sudo && \ apt-get clean && \ cd /opt && \ wget -q https://www-us.apache.org/dist/tomcat/tomcat-9/v9.0.14/bin/apache-tomcat-9.0.14.tar.gz && \ tar xf apache-tomcat-9.0.14.tar.gz && \ rm apache-tomcat-9.0.14.tar.gz && \ mv apache-tomcat-9.0.14 apache-tomcat && \ ln -sf /dev/stdout /opt/apache-tomcat/logs/catalina.out ENTRYPOINT /opt/apache-tomcat/bin/startup.sh && sleep 120
catalina.outを、/dev/stdoutのリンクにしています。
ln -sf /dev/stdout /opt/apache-tomcat/logs/catalina.out
起動はstartup.shで、ですが、そのままだと終了してしまうのでsleepを…。
ENTRYPOINT /opt/apache-tomcat/bin/startup.sh && sleep 120
ちなみに、Apache Tomcatのオフィシャルイメージでは、こんなことをせずにcatalina.shを実行しています。
CMD ["catalina.sh", "run"]
これで、ログの内容が標準出力に書き出されます。
…話を戻して、Dockerイメージをビルド。
$ docker build -t kazuhira/tomcat:9 .
起動。
$ docker container run --rm --name tomcat kazuhira/tomcat:9
すると、catalina.outに出力される内容がずらずらと標準出力に現れます。
Tomcat started. 02-Jan-2019 08:27:06.576 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server version name: Apache Tomcat/9.0.14 02-Jan-2019 08:27:06.577 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server built: Dec 6 2018 21:13:53 UTC 02-Jan-2019 08:27:06.578 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server version number: 9.0.14.0 02-Jan-2019 08:27:06.578 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log OS Name: Linux 02-Jan-2019 08:27:06.578 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log OS Version: 4.15.0-43-generic 02-Jan-2019 08:27:06.578 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Architecture: amd64 02-Jan-2019 08:27:06.578 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Java Home: /usr/lib/jvm/java-8-openjdk-amd64/jre 02-Jan-2019 08:27:06.578 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log JVM Version: 1.8.0_181-8u181-b13-2~deb9u1-b13 02-Jan-2019 08:27:06.578 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log JVM Vendor: Oracle Corporation 02-Jan-2019 08:27:06.578 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log CATALINA_BASE: /opt/apache-tomcat 02-Jan-2019 08:27:06.579 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log CATALINA_HOME: /opt/apache-tomcat 02-Jan-2019 08:27:06.579 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.util.logging.config.file=/opt/apache-tomcat/conf/logging.properties 02-Jan-2019 08:27:06.579 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager 02-Jan-2019 08:27:06.579 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djdk.tls.ephemeralDHKeySize=2048 02-Jan-2019 08:27:06.579 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.protocol.handler.pkgs=org.apache.catalina.webresources 02-Jan-2019 08:27:06.579 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dorg.apache.catalina.security.SecurityListener.UMASK=0027 02-Jan-2019 08:27:06.579 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dignore.endorsed.dirs= 02-Jan-2019 08:27:06.580 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dcatalina.base=/opt/apache-tomcat 02-Jan-2019 08:27:06.580 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dcatalina.home=/opt/apache-tomcat 02-Jan-2019 08:27:06.580 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.io.tmpdir=/opt/apache-tomcat/temp 02-Jan-2019 08:27:06.580 INFO [main] org.apache.catalina.core.AprLifecycleListener.lifecycleEvent The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: [/usr/java/packages/lib/amd64:/usr/lib/x86_64-linux-gnu/jni:/lib/x86_64-linux-gnu:/usr/lib/x86_64-linux-gnu:/usr/lib/jni:/lib:/usr/lib] 02-Jan-2019 08:27:06.659 INFO [main] org.apache.coyote.AbstractProtocol.init Initializing ProtocolHandler ["http-nio-8080"] 02-Jan-2019 08:27:06.715 INFO [main] org.apache.coyote.AbstractProtocol.init Initializing ProtocolHandler ["ajp-nio-8009"] 02-Jan-2019 08:27:06.717 INFO [main] org.apache.catalina.startup.Catalina.load Server initialization in [438] milliseconds 02-Jan-2019 08:27:06.742 INFO [main] org.apache.catalina.core.StandardService.startInternal Starting service [Catalina] 〜省略〜
「docker container logs」でも、確認することができます。
$ docker logs tomcat | head -n 10 Tomcat started. 02-Jan-2019 08:27:06.576 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server version name: Apache Tomcat/9.0.14 02-Jan-2019 08:27:06.577 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server built: Dec 6 2018 21:13:53 UTC 02-Jan-2019 08:27:06.578 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server version number: 9.0.14.0 02-Jan-2019 08:27:06.578 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log OS Name: Linux 02-Jan-2019 08:27:06.578 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log OS Version: 4.15.0-43-generic 02-Jan-2019 08:27:06.578 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Architecture: amd64 02-Jan-2019 08:27:06.578 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Java Home: /usr/lib/jvm/java-8-openjdk-amd64/jre 02-Jan-2019 08:27:06.578 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log JVM Version: 1.8.0_181-8u181-b13-2~deb9u1-b13 02-Jan-2019 08:27:06.578 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log JVM Vendor: Oracle Corporation
なお、先ほどのDockerfileのシンボリックリンクを作成している箇所をコメントアウトしてビルドして
mv apache-tomcat-9.0.14 apache-tomcat # ln -sf /dev/stdout /opt/apache-tomcat/logs/catalina.out
起動すると、ログは以下の1行だけになります。
$ docker container run --rm --name tomcat kazuhira/tomcat:9 Tomcat started.
というわけで、catalina.outの内容を標準出力に書き出すことができるようになったことが、確認できました、と。
気になること
シンボリックリンクにしたファイルに書き出すのは、ログインユーザーと実行ユーザーが異なると、うまくいかないようですね?
シンボリックリンクの作成をDockerfile内で作成した別ユーザーで行い、かつ起動も別ユーザーですると、こんな感じに…。
touch: cannot touch '/opt/apache-tomcat/logs/catalina.out': Permission denied Tomcat started. /opt/apache-tomcat/bin/catalina.sh: 1: eval: cannot create /opt/apache-tomcat/logs/catalina.out: Permission denied
この時のDockerfile。tomcatというユーザーを作成し、sudoで一時的にユーザーを変更して実行しています。
FROM openjdk:8 RUN adduser --disabled-login --gecos '' tomcat RUN apt-get update -y && \ apt-get install -y wget sudo && \ apt-get clean && \ cd /opt && \ wget -q https://www-us.apache.org/dist/tomcat/tomcat-9/v9.0.14/bin/apache-tomcat-9.0.14.tar.gz && \ tar xf apache-tomcat-9.0.14.tar.gz && \ rm apache-tomcat-9.0.14.tar.gz && \ mv apache-tomcat-9.0.14 apache-tomcat && \ chown -R tomcat.tomcat apache-tomcat && \ sudo -u tomcat ln -sf /dev/stdout /opt/apache-tomcat/logs/catalina.out ENTRYPOINT sudo -u tomcat /opt/apache-tomcat/bin/startup.sh && sleep 120
「sudo -u tomcat」で
sudo -u tomcat /opt/apache-tomcat/bin/startup.sh
ちなみに、こうするとうまくいきます。
FROM openjdk:8 RUN adduser --disabled-login --gecos '' tomcat RUN apt-get update -y && \ apt-get install -y wget sudo && \ apt-get clean && \ cd /opt && \ wget -q https://www-us.apache.org/dist/tomcat/tomcat-9/v9.0.14/bin/apache-tomcat-9.0.14.tar.gz && \ tar xf apache-tomcat-9.0.14.tar.gz && \ rm apache-tomcat-9.0.14.tar.gz && \ mv apache-tomcat-9.0.14 apache-tomcat && \ chown -R tomcat.tomcat apache-tomcat && \ sudo -u tomcat ln -sf /dev/stdout /opt/apache-tomcat/logs/catalina.out USER tomcat ENTRYPOINT /opt/apache-tomcat/bin/startup.sh && sleep 120
「USER tomcat」でユーザーを指定するようにしました。
この時の、/dev/stdoutの差。
rootで実行し、sudoで切り替えようとした場合。
# ls -l /dev/stdout lrwxrwxrwx 1 root root 15 Jan 2 08:45 /dev/stdout -> /proc/self/fd/1 # ls -l /proc/self/fd/1 lrwx------ 1 root root 64 Jan 2 08:45 /proc/self/fd/1 -> /dev/pts/0
「USER tomcat」と指定した場合。
$ ls -l /dev/stdout lrwxrwxrwx 1 root root 15 Jan 2 08:47 /dev/stdout -> /proc/self/fd/1 $ ls -l /proc/self/fd/1 lrwx------ 1 tomcat tomcat 64 Jan 2 08:47 /proc/self/fd/1 -> /dev/pts/0
1番目のFile Descriptorのオーナーが異なりますね。
参考)