我正在部署第三方应用程序,以符合12个因素的build议 ,其中一个要点说明应将应用程序日志打印到stdout / stderr:然后集群软件可以收集它。
但是,应用程序只能写入文件或系统日志。 我如何打印这些日志呢?
nginx Dockerfile给出了一个惊人的配方:
# 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
简单地说,应用程序可以继续将其作为文件写入,但是作为结果,这些行会转到stdout
& stderr
!
另一个问题是, 当父母离开时杀死孩子的过程 ,我得到了帮助解决这个问题的答案。
这样,我们configuration应用程序,使其logging到一个文件,并不断tail -f
。 幸运的是, tail
可以接受--pid PID
:当指定的进程退出时它会退出。 我们把$$
放在那里:当前shell的PID。
作为最后一步,已启动的应用程序将被exec
,这意味着当前的shell已被完全replace为该应用程序。
Runner脚本, run.sh
,将如下所示:
#! /usr/bin/env bash set -eu rm -rf /var/log/my-application.log tail --pid $$ -F /var/log/my-application.log & exec /path/to/my-application --logfile /var/log/my-application.log
注意:通过使用tail -F
我们列出文件名,即使它们稍后出现,它也会读取它们!
最后,简单的Dockerfile:
FROM ubuntu ADD run.sh /root/run.sh CMD ['/root/run.sh']
注意:为了解决一些非常奇怪的tail -f
行为(说“已经被replace为远程文件,放弃这个名字”),我尝试了另一种方法:所有已知的日志文件都是在启动时创build和截断的:确保它们存在,只有这样 – 尾巴:
#! /usr/bin/env bash set -eu LOGS=/var/log/myapp/ ( umask 0 && truncate -s0 $LOGS/http.{access,error}.log ) tail --pid $$ -n0 -F $LOGS/* & exec /usr/sbin/apache2 -DFOREGROUND
对于nginx,你可以像这样将nginx.conf
指向/dev/stderr
和/dev/stdout
user nginx; worker_processes 4; error_log /dev/stderr; http { access_log /dev/stdout main; ...
和你的Dockerfile
条目应该是
/usr/sbin/nginx -g 'daemon off;'