容器日志记录如何工作?

时间:2020-04-29 15:28:28

标签: docker logging kubernetes

我已经在很多Docker容器中看到了创建日志文件并像这样进行日志记录的常见做法

/var/log/container.log
...

tail  -f /var/log/container.log

某种程度上,输出似乎是由容器运行时日志驱动程序获取的。所以如果我跑

docker container logs container

这将显示文件container.log

的输出

我知道任何容器的最佳做法是登录stdoutstderr,但是我不明白为什么第一个选项有效(创建文件并在其上运行tail)。是因为tail的输出由驱动程序日志获取,并将其与stdout的内容合并?

非常感谢您的帮助。 谢谢。

1 个答案:

答案 0 :(得分:2)

tail -f方法实际上不是最佳实践。

如您所述,运行进程并生成日志的正确方法是让其将其输出直接写入stdout和stderr,docker logs将捕获它们。您可以配置Docker的日志记录层以将它们发送到其他地方。如果您使用Kubernetes这样的集群基础架构,则可以配置其日志记录层以捕获日志,而无需修改应用程序代码。

#!/bin/sh
# I am the script that runs the main container process.
# Run a single process, as a foreground process; when that
# process ends, the container exits.
exec some_server --no-daemon --log-file /dev/stdout

看到tail -f时,通常看起来像这样:

#!/bin/sh
# Start something as a background process.
something --log-file /var/log/something.log &
# Hackily keep the container from exiting.
tail -f /var/log/something.log

主要容器过程是tail过程。当tail退出时,容器将停止,如果您docker stop容器,则信号将到达tail。哦,顺便说一句,副作用是,正在运行一个something进程,但是如果Docker失败,则无法注意到它。尽管如此,由于tail进程是主要进程,并且tail -f永远不会退出,因此可以使容器保持运行状态,并使基于文件的日志对容器的标准输出可见。

这里另一种有趣的方法是Docker Hub httpd映像的作用:它将日志记录设置为指向文件,但是该文件的默认内容是指向/dev/stdout的符号链接。

RUN mkdir /var/log/something \
 && ln -s /dev/stdout /var/log/something/something.log
CMD ["something", "--log-file", "/var/log/something/something.log"]

这很有趣,因为默认行为是将内容写入该日志文件,但实际上它是/dev/stdout特殊设备,因此它将转到进程(主容器进程)的stdout。如果您想将其捕获到文件中,则可以将自己的目录绑定安装到/var/log/something上,这将阻止符号链接。