我已经在很多Docker容器中看到了创建日志文件并像这样进行日志记录的常见做法
/var/log/container.log
...
tail -f /var/log/container.log
某种程度上,输出似乎是由容器运行时日志驱动程序获取的。所以如果我跑
docker container logs container
这将显示文件container.log
我知道任何容器的最佳做法是登录stdout
和stderr
,但是我不明白为什么第一个选项有效(创建文件并在其上运行tail)。是因为tail
的输出由驱动程序日志获取,并将其与stdout的内容合并?
非常感谢您的帮助。 谢谢。
答案 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
上,这将阻止符号链接。