日志记录是任何生产应用程序中至关重要的一部分。当出现问题时,日志可以是恢复服务的关键工具,所以它们需要做好。在 Linux 系统上,我们期望通过一些常见方式与应用程序日志交互,有些方式更好。如果您在一台计算机上运行应用程序进程,您可能希望将输出发送到一个您可以查看的本地日志文件中。或者您可能期望输出简单地记录在内核缓冲区中,可以从 dmesg 中读取。或者,在许多现代 Linux 发行版中使用 systemd,您可能希望能够从 journalctl 中获取日志。由于容器的约束以及 Docker 的构造方式,这些方式都至少需要您进行一些配置才能运作。但这没关系,因为 Docker 具有一流的日志记录支持。
Docker 在几个关键方面让日志记录变得更容易。首先,它能捕获其管理的容器中应用程序的所有正常文本输出。容器中发送到 stdout 或 stderr 的任何内容都会被 Docker 守护进程捕获,并流式传输到可配置的日志记录后端。其次,与 Docker 的许多其他部分一样,该系统也是可插拔的,有许多功能强大的插件可供使用。不过,我们先不要深入探讨。
docker 容器日志
我们将从最简单的 Docker 使用场景开始:默认的日志记录机制。 这种机制存在一些限制,我们一会儿会解释的,但对于大多数常见的使用情况来说,它运行良好,并且非常方便。 如果您在开发过程中使用 Docker,那么这可能是您唯一使用的日志记录策略。 这种日志记录方法从一开始就存在,被广泛理解和支持。 机制是 json-file 方法。 docker container logs 命令将大多数方法露给用户。
正如其名所示,当您运行默认的 json 文件日志记录配置时,应用程序的日志会被 Docker 守护进程流式传输到每个容器的 JSON 文件中。这样,我们就可以随时检索任何容器的日志。
我们可以通过启动 nginx 容器来显示一些日志:
docker container run --rm -d --name nginx-test --rm nginx:latest
然后,使用如何命令查看日志:
docker container logs nginx-test
这一点很好,因为 Docker 允许你根据需要从命令行远程获取日志。这对低容量日志记录非常有用。
支持此日志记录的实际文件位于 Docker 服务器本身,默认情况下位于 /var/lib/docker/containers/<container_id>/ 中,其中 <container_id> 由实际容器 ID 代替。如果查看名为 <container_id>-json.log 的文件,你会发现这是一个每行代表一个 JSON 对象的文件。它看起来是这样的
log字段正是有关进程发送到 stdout 的内容;stream字段告诉我们这是 stdout 而不是 stderr,time字段提供了 Docker 守护进程收到日志的准确时间。这是一种不常见的日志格式,但它是结构化的,而不仅仅是原始流,这对以后处理日志很有帮助。
与日志文件一样,你也可以使用 docker container logs -f 实时尾随 Docker 日志:
docker container logs -f nginx-test
这看起来与通常的 docker 容器日志完全相同,但客户端会继续等待并显示从服务器接收到的新消息,就像 Linux 命令行 tail -f 一样。你可以随时输入 Ctrl-C 退出日志流:
要将日志输出限制为较新的日志,可以使用 --since 选项,只显示指定 RFC 3339 日期(如 2002-10-02T10:00:00-05:00)、Unix 时间戳(如 1450071961)、标准时间戳(如 20220731)或 Go 持续时间字符串(如 5m45s)之后的日志。你也可以使用 --tail,并在后面加上你希望尾随的行数。
退出容器
docker container stop nginx-test
对于单主机日志记录而言,这种机制相当不错。它的不足之处在于日志轮换、日志轮换后的远程访问以及大容量日志的磁盘空间占用。尽管该机制是由 JSON 文件支持的,但它的性能足够好,如果这是你的解决方案,大多数生产应用程序都可以采用这种方式记录日志。但如果你的环境比较复杂,你会需要更强大的集中日志记录功能。
注:
dockerd 的默认设置目前还不能启用日志轮转。如果是在生产环境中运行,需要通过命令行或 daemon.json 配置文件指定 --log-opt max-size 和 --log-opt max-file 设置。除非你还设置了 max-size 来告诉 Docker 何时轮换日志,否则 max-file 没有任何作用。启用此选项后,docker 容器日志机制将只返回当前日志文件中的数据。
更高级的日志
在默认机制不够用的时候,尤其是在大规模使用情况下,Docker 也可以通过插件支持可配置的日志后端。这些插件不断增加。目前支持的插件有我们之前描述的 json-file,还有 syslog、fluentd、journald、gelf、awslogs、splunk、gcplogs、local 以及 logentries,用于将日志发送到各种流行的日志框架和服务。
对于大规模运行 Docker 而言,目前最简单的支持选项是从 Docker 直接将容器日志发送到 syslog。你可以在 Docker 命令行中使用 --log-driver=syslog 选项指定这一点,或者在所有容器的 daemon.json 文件中将其设置为默认值。
注:
daemon.json 文件是 dockerd 服务器的配置文件。它通常位于服务器上的 /etc/docker/ 目录中。对于 Docker Desktop,可以在用户界面的 "偏好设置"→"Docker 引擎 "中编辑该文件。如果更改了该文件,就需要重启 Docker Desktop 或 dockerd 守护进程。
关于大多数日志插件,非常重要的一点需要注意:它们默认为阻塞模式,这意味着日志回压可能会给应用程序带来问题。你可以通过设置 --log-opt mode=non-blocking 来改变这种行为,然后将日志的最大缓冲区大小设置为类似 --log-opt max-buffer-size=4m 的大小。设置完成后,当缓冲区满时,应用程序将不再阻塞。相反,内存中最旧的日志会被删除。同样,在此需要权衡可靠性和企业对接收所有日志的需求。
以上步骤,并没有解释每个docker命令的含义,是比较基础的操作,如果您对以上的命令不太熟悉,可以参考我的docekr课程,有对各类命令的详细讲解:Docker 实战_在线视频教程-CSDN程序员研修院