使Docker应用程序写入标准输出


49

我正在按照12要素咨询意见部署第3方应用程序,其中之一是应将应用程序日志打印到stdout / stderr:然后集群软件可以收集它。

但是,该应用程序只能写入文件或syslog。我该如何打印这些日志?


他们已经准备进入syslog。您可以从那里接他们!
迈克尔·汉普顿

@MichaelHampton看起来不错,但是Docker运行一个可以写入stdout的进程,这听起来像是将其中的两个结合起来了?
kolypto

1
您可以让守护进程使用syslog,并让前台进程打印?
qkrijger 2014年

@qkrijger,好点!现在,如果有人有经验……?
kolypto

Answers:


107

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

简而言之,该应用程序可以继续以文件形式写入该文件,但结果行将转到stdoutstderr


2
这个。是的。只是。辉煌。而且用途广泛。
spacediver 2014年

11
与此有关的一件事是,当您正在运行的事物坚持以非根进程的形式将自身派生到后台时。我在使用squid3,然后在使用权限时遇到了麻烦/dev/stdout
mikepurvis 2014年

4
这并不总是有效的-例如,如果应用程序尝试查找文件,则此方法通常将无效。
mixja

链接已
断开

4
一切都是胜利的档案。
RubberDuck

16

在另一个问题中,当父母退出时杀死子进程,我得到了有助于解决该问题的响应。

这样,我们对应用程序进行配置,使其记录到文件中并连续进行tail -f。幸运的是,tail可以接受--pid PID:当指定的进程退出时它将退出。我们放在$$这里:当前外壳的PID。

最后一步是启动已启动的应用程序exec,这意味着当前的外壳程序将完全被该应用程序替换。

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行为(它表示“已被远程文件替换。放弃此名称”),我尝试了另一种方法:所有已知的日志文件在启动时都会创建并被截断:这样我可以确保它们存在,然后-拖尾它们:

#! /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

尤其是对于Apache服务器,我使用的是管道日志(httpd.apache.org/docs/2.4/logs.html#piped),看起来很有效。
php-coder

该解决方案可以解决与alpine类似的问题,并且在tail不使用--pid选项的情况下,在BusyBox上似乎可以正常使用。
瑞安

解决方法对我有用。非常有用,谢谢。
塔玛斯·卡尔曼

8

对于Docker容器中的后台进程,例如,我可以使用exec与/ bin / bash连接。

echo "test log1" >> /proc/1/fd/1

这会将输出发送到pid 1的stdout,这是docker拾取的一个。


1
这是正确的答案。日志应发送到PID1的stdout,如果您的应用程序在其他PID下运行,则docker logs或不会看到该日志kubectl logs。我有一个通过crontab计划任务的容器,该容器未作为PID1运行。
leeman24

6

对于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;'

当主进程未按以下方式运行时不起作用root
peedee '18
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.