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

kol*_*pto 71 cluster logging docker coreos

我正在部署一个符合12 因素建议的 3rd 方应用程序,其中一点告诉应用程序日志应该打印到 stdout/stderr:然后集群软件可以收集它。

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

kol*_*pto 141

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
Run Code Online (Sandbox Code Playgroud)

简单地说,应用程序可以继续将其作为文件写入,但结果行将转到stdout& stderr

  • 与此有关的一件事是,当您正在运行的东西坚持将自己作为非 root 进程分叉到后台时。我在 `squid3` 上遇到了这个问题,然后它在 `/dev/stdout` 上的权限有问题。 (13认同)
  • 这并不总是有效 - 例如,如果应用程序尝试查找文件,则此方法通常不起作用。 (6认同)
  • 这个。是。只是。杰出的。而且用途广泛。 (5认同)
  • 一切都是为了胜利。 (5认同)
  • 请注意,这适用于大多数情况,但是如果您的应用程序执行日志记录不是以 PID 1 运行,那么日志将不会重定向到 Docker 从中读取的标准输出。 (2认同)

Pie*_*ter 32

对于 docker 容器中的后台进程,例如使用 exec 连接到 /bin/bash 我能够使用。

echo "test log1" >> /proc/1/fd/1
Run Code Online (Sandbox Code Playgroud)

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

  • 这是正确答案。日志应发送到 PID1 的标准输出,如果您的应用程序在另一个 PID 下运行,`docker logs` 或 `kubectl logs` 将看不到它。我有一个通过 crontab 调度任务的容器,它不是作为 PID1 运行的。 (3认同)

kol*_*pto 19

在另一个问题中,当父进程退出时杀死子进程,我得到了帮助解决这个问题的回复。

通过这种方式,我们配置了应用程序,使其记录到文件中,并持续记录到文件中tail -f。幸运的是,tail可以接受--pid PID:它会在指定进程退出时退出。我们把$$:当前shell的PID。

作为最后一步,启动的应用程序是exec'ed,这意味着当前的 shell 被该应用程序完全替换。

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
Run Code Online (Sandbox Code Playgroud)

注意:通过使用tail -F我们列出文件名,即使它们稍后出现,它也会读取它们!

最后,简约的 Dockerfile:

FROM ubuntu
ADD run.sh /root/run.sh
CMD ['/root/run.sh']
Run Code Online (Sandbox Code Playgroud)

注意:为了解决一些非常奇怪的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
Run Code Online (Sandbox Code Playgroud)


小智 7

对于 nginx,您可以nginx.conf指向/dev/stderr/dev/stdout喜欢这个

user  nginx;
worker_processes  4;
error_log  /dev/stderr;
http {
    access_log  /dev/stdout  main;
...
Run Code Online (Sandbox Code Playgroud)

你的Dockerfile条目应该是

/usr/sbin/nginx -g 'daemon off;'
Run Code Online (Sandbox Code Playgroud)

  • 当主进程未以“root”身份运行时不起作用 (4认同)