Heroku将其Twelve-Factor App manifest中的日志描述为简单的事件流:
日志是从所有正在运行的进程和支持服务的输出流中收集的聚合的,按时间排序的事件流。原始格式的日志通常是文本格式,每行一个事件(尽管异常的回溯可能跨越多行)。日志没有固定的开头或结尾,但只要应用正在运行,就会持续流动。
此外,应用只需将日志写入stdout
,将任务留给"环境"。
十二因素应用程序从不关心其输出流的路由或存储。它不应该尝试写入或管理日志文件。相反,每个正在运行的进程将其未缓冲的事件流写入stdout。在本地开发期间,开发人员将在其终端的前台查看此流以观察应用程序的行为。
在登台或生产部署中,每个进程的流将由执行环境捕获,与来自应用程序的所有其他流进行整理,并路由到一个或多个最终目的地以供查看和长期存档。这些归档目标对应用程序不可见或可由应用程序配置,而是由执行环境完全管理。开源日志路由器(例如Logplex和Fluent)可用于此目的。
那么在可靠性,效率和易用性方面,在docker环境中实现这一目标的最佳方法是什么?我想到了以下问题:
docker logs
)是否安全?stdout
直接重定向到文件(磁盘空间)吗?docker run --volume=[]
)内?答案 0 :(得分:28)
Docker 1.6 introduced logging drivers的概念,提供对日志输出的更多控制。 --log-driver
标记配置stdout
&应该指示来自容器中运行的进程的stderr
。另请参阅Configuring Logging drivers。
有几个司机可用。请注意,除json-file
之外的所有这些都禁止使用docker logs
来收集容器日志。
/var/lib/docker/containers/<containerid>/<containerid>-json.log
--log-opt
以通过TCP,UDP或Unix域套接字将日志消息定向到指定的syslog。同时禁用docker logs
* Docker 1.8中的新功能
** Docker 1.9中的新功能
例如:
docker run --log-driver=syslog --log-opt syslog-address=tcp://10.0.0.10:1514 ...
这是Docker推荐的软件解决方案,可将其日志消息写入stdout
&amp; stderr
。但是,某些软件不会将日志消息写入stdout/stderr
。例如,它们会写入日志文件或syslog。在这些情况下,以下原始答案中的一些细节仍然适用。回顾一下:
如果应用程序写入本地日志文件,请从主机安装卷(或使用data-only container到容器并将日志消息写入该位置。
如果应用程序写入syslog,则有几个选项:
/dev/log
将主机的syslog套接字(-v /dev/log:/dev/log
)挂载到容器,发送到主机的syslog。 不要忘记容器中的任何日志应该像在主机操作系统上一样旋转。
依赖Docker自己的日志工具(docker logs)是否安全?
docker logs
每次打印整个流,而不仅仅是新日志,因此它不合适。 docker logs --follow
将提供tail -f
- 类似功能,但随后您将一直运行docker CLI命令。因此,虽然运行docker logs
安全,但它并不是最佳的。
运行未缓存的docker并将其输出视为日志记录流是否安全?
您可以使用systemd而不是daemonize启动容器,从而捕获systemd日志中的所有stdout,然后可以由您自己管理的主机管理。
stdout可以直接重定向到文件(磁盘空间)吗?
当然,您可以使用docker run ... > logfile
执行此操作,但它会感觉更脆弱,更难以自动化和管理。
如果使用文件,它应该在docker镜像内还是在绑定卷内(docker run --volume = [])?
如果您在容器内写入,那么您需要在容器中运行logrotate或其他东西来管理日志文件。最好从主机安装卷并使用主机的日志轮转守护程序控制它。
需要进行logrotation吗?
当然,如果应用程序写入日志,您需要像在本机OS环境中一样旋转它们。但是如果您在容器内部写入,则更难,因为日志文件位置不可预测。如果在主机上轮换,则日志文件将存在,例如使用devicemapper作为存储驱动程序/var/lib/docker/devicemapper/mnt/<containerid>/rootfs/...
。需要一些丑陋的包装才能让logrotate在该路径下找到日志。
将stdout直接重定向到logshipper(以及哪个logshipper)是否安全?
最好使用syslog并让日志收集器处理syslog。
命名管道(又称FIFO)是一个选项吗?
命名管道并不理想,因为如果管道的读取端死亡,编写器(容器)将会出现断管。即使该事件由应用程序处理,它也会被阻止,直到再次有读者。另外,它绕过了docker logs
。
另见post on fluentd with docker。
请参阅Jeff Lindsay的工具logspout,该工具从正在运行的容器中收集日志并根据需要对其进行路由。
最后,请注意容器中的stdout会在/var/lib/docker/containers/<containerid>/<containerid>-json.log
中记录到主机上的文件。