如何查看Docker日志?

Docker是一种流行的操作系统级虚拟化平台,它允许我们以容器的形式交付应用程序,简单来说,容器是具有自己的软件、库和配置文件的隔离环境。

与任何其他现代软件一样,记录事件和消息(如警告和错误)是日志记录的固有部分,它可以帮助您调试应用程序和生产问题。

我们将介绍一些简单的方法,以便您可以管理和监控容器的日志。接下来让我们开始吧。

Docker日志命令

获取容器日志的基本语法如下:

$ docker logs [OPTIONS] 

$ docker container logs [OPTIONS] 

这两种语法本质上是相同的,所以我们将在本文中重点关注其他命令,即docker logs

但请注意,上述命令仅适用于使用json-filejournald日志驱动程序启动的容器。

这里的OPTIONSdocker logs命令的支持标志,下面列出了可用的标志:

名称,简写 默认值 描述
--details 显示提供给日志的额外详细信息。
--follow-f 跟踪日志输出
--since 显示自时间戳(例如2021-08-28T15:23:37Z)或相对时间(例如56m表示56分钟)后的日志。
--tail , -n all 显示日志末尾的行数。
--timestamps, -t 显示时间戳。
--until 显示时间戳(例如2021-08-28T15:23:37Z)或相对时间(例如56m表示56分钟)之前的日志。

示例:

$ docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS        PORTS     NAMES
28913415ed22   nginx     "/docker-entrypoint.…"   2 seconds ago   Up 1 second   80/tcp    gifted_edison
$ docker logs 28913415ed22
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
2021/08/28 09:02:59 [notice] 1#1: using the "epoll" event method
2021/08/28 09:02:59 [notice] 1#1: nginx/1.21.1
2021/08/28 09:02:59 [notice] 1#1: built by gcc 8.3.0 (Debian 8.3.0-6)
2021/08/28 09:02:59 [notice] 1#1: OS: Linux 5.8.0-1039-azure
2021/08/28 09:02:59 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576
2021/08/28 09:02:59 [notice] 1#1: start worker processes
2021/08/28 09:02:59 [notice] 1#1: start worker process 31
2021/08/28 09:02:59 [notice] 1#1: start worker process 32
$

Docker日志位置

Docker,默认情况下,捕获所有容器的标准输出(和标准错误),并使用JSON格式将它们写入文件中。这是通过使用JSON文件日志记录驱动程序或json-file来实现的。这些日志默认存储在文件系统/var/lib/docker下特定于容器的位置。

/var/lib/docker/containers//-json.log

以我的redis容器为例,可以使用下面的代码段检查其json日志文件:

$ docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS                                   NAMES
551c9273bbea   redis     "docker-entrypoint.s…"   19 minutes ago   Up 19 minutes   6379/tcp                                redis
6cc871763df1   nginx     "/docker-entrypoint.…"   7 hours ago      Up 7 hours      0.0.0.0:8080->80/tcp, :::8080->80/tcp   nostalgic_wescoff
$ sudo ls -l /var/lib/docker/containers/551c9273bbea6eaf66523ed735866b9ebe6924c3b504dfeb44bef90e69d59c73/551c9273bbea6eaf66523ed735866b9ebe6924c3b504dfeb44bef90e69d59c73-json.log
-rw-r----- 1 root root 1437 Aug 28 16:53 /var/lib/docker/containers/551c9273bbea6eaf66523ed735866b9ebe6924c3b504dfeb44bef90e69d59c73/551c9273bbea6eaf66523ed735866b9ebe6924c3b504dfeb44bef90e69d59c73-json.log
$ sudo tail -10 /var/lib/docker/containers/551c9273bbea6eaf66523ed735866b9ebe6924c3b504dfeb44bef90e69d59c73/551c9273bbea6eaf66523ed735866b9ebe6924c3b504dfeb44bef90e69d59c73-json.log
{"log":"1:C 28 Aug 2021 16:53:42.160 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oon","stream":"stdout","time":"2021-08-28T16:53:42.16031257Z"}
{"log":"1:C 28 Aug 2021 16:53:42.160 # Redis version=6.2.5, bits=64, commit=00000000, modified=0, pid=1, just startedn","stream":"stdout","time":"2021-08-28T16:53:42.160337871Z"}
{"log":"1:C 28 Aug 2021 16:53:42.160 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.confn","stream":"stdout","time":"2021-08-28T16:53:42.160342171Z"}
{"log":"1:M 28 Aug 2021 16:53:42.160 * monotonic clock: POSIX clock_gettimen","stream":"stdout","time":"2021-08-28T16:53:42.160792578Z"}
{"log":"1:M 28 Aug 2021 16:53:42.161 * Running mode=standalone, port=6379.n","stream":"stdout","time":"2021-08-28T16:53:42.161148683Z"}
{"log":"1:M 28 Aug 2021 16:53:42.161 # Server initializedn","stream":"stdout","time":"2021-08-28T16:53:42.161170984Z"}
{"log":"1:M 28 Aug 2021 16:53:42.161 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.n","stream":"stdout","time":"2021-08-28T16:53:42.161186984Z"}
{"log":"1:M 28 Aug 2021 16:53:42.161 * Ready to accept connectionsn","stream":"stdout","time":"2021-08-28T16:53:42.161484389Z"}
$

显示额外细节

要显示提供给日志的额外细节,请使用--details标志。

示例:

$ docker logs 6cc871763df1 --details
 /docker-entrypoint.sh: /docker-entrypoint.d/ 不为空,将尝试执行配置
 /docker-entrypoint.sh: 在 /docker-entrypoint.d/ 中查找 shell 脚本
 /docker-entrypoint.sh: 启动 /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
 10-listen-on-ipv6-by-default.sh: 信息: 获取 /etc/nginx/conf.d/default.conf 的校验和
 10-listen-on-ipv6-by-default.sh: 信息: 在 /etc/nginx/conf.d/default.conf 中启用 IPv6 监听
 /docker-entrypoint.sh: 启动 /docker-entrypoint.d/20-envsubst-on-templates.sh
 /docker-entrypoint.sh: 启动 /docker-entrypoint.d/30-tune-worker-processes.sh
 /docker-entrypoint.sh: 配置完成; 准备启动
 2021/08/28 10:29:05 [notice] 1#1: 使用 "epoll" 事件方法
 2021/08/28 10:29:05 [notice] 1#1: nginx/1.21.1
 2021/08/28 10:29:05 [notice] 1#1: 由 gcc 8.3.0 (Debian 8.3.0-6) 构建
 2021/08/28 10:29:05 [notice] 1#1: 操作系统: Linux 5.8.0-1039-azure
 2021/08/28 10:29:05 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576
 2021/08/28 10:29:05 [notice] 1#1: 启动 worker 进程
 2021/08/28 10:29:05 [notice] 1#1: 启动 worker 进程 33
 2021/08/28 10:29:05 [notice] 1#1: 启动 worker 进程 34
 172.17.0.1 - - [28/Aug/2021:10:29:26 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.68.0" "-"
$

跟随日志输出

您可以使用 --follow-f 标志来跟随日志输出。这样可以监视连续的 STDOUTSTDERR 中的日志流中的新更新。

示例:

$ docker logs 6cc871763df1 -f
/docker-entrypoint.sh: /docker-entrypoint.d/ 不为空,将尝试执行配置
/docker-entrypoint.sh: 在 /docker-entrypoint.d/ 中查找 shell 脚本
/docker-entrypoint.sh: 启动 /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: 信息: 获取 /etc/nginx/conf.d/default.conf 的校验和
10-listen-on-ipv6-by-default.sh: 信息: 在 /etc/nginx/conf.d/default.conf 中启用 IPv6 监听
/docker-entrypoint.sh: 启动 /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: 启动 /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: 配置完成; 准备启动
2021/08/28 10:29:05 [notice] 1#1: 使用 "epoll" 事件方法
2021/08/28 10:29:05 [notice] 1#1: nginx/1.21.1
2021/08/28 10:29:05 [notice] 1#1: 由 gcc 8.3.0 (Debian 8.3.0-6) 构建
2021/08/28 10:29:05 [notice] 1#1: 操作系统: Linux 5.8.0-1039-azure
2021/08/28 10:29:05 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576
2021/08/28 10:29:05 [notice] 1#1: 启动 worker 进程
2021/08/28 10:29:05 [notice] 1#1: 启动 worker 进程 33
2021/08/28 10:29:05 [notice] 1#1: 启动 worker 进程 34
172.17.0.1 - - [28/Aug/2021:10:29:26 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.68.0" "-"

查看日志尾部

可以使用 --tail-n 标志来查看容器日志的尾部输出数量。默认情况下,该标志假定参数为 all,显示完整的日志流。要显示日志末尾的固定行数,请在 --tail-n 标志后面指定一个正整数。

示例:

$ docker logs 6cc871763df1 -n 10
/docker-entrypoint.sh: 配置完成;准备启动
2021/08/28 10:29:05 [notice] 1#1: 使用“epoll”事件方法
2021/08/28 10:29:05 [notice] 1#1: nginx/1.21.1
2021/08/28 10:29:05 [notice] 1#1: 编译器版本为gcc 8.3.0(Debian 8.3.0-6)
2021/08/28 10:29:05 [notice] 1#1: 操作系统为Linux 5.8.0-1039-azure
2021/08/28 10:29:05 [notice] 1#1: 获取文件描述符限制(RLIMIT_NOFILE):1048576:1048576
2021/08/28 10:29:05 [notice] 1#1: 启动工作进程
2021/08/28 10:29:05 [notice] 1#1: 启动工作进程33
2021/08/28 10:29:05 [notice] 1#1: 启动工作进程34
172.17.0.1 - - [28/Aug/2021:10:29:26 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.68.0" "-"
$

显示自从

我们可以使用--since标志来限制日志输出,并给出一个时间戳,如绝对值的语法2021-08-28T15:23:37Z或相对值的语法56m,表示56分钟。

--since选项仅显示给定日期后生成的容器日志。您可以将日期指定为RFC 3339日期、UNIX时间戳或Go持续时间字符串(例如1m30s3h)。如果您没有在时间戳的末尾提供Z+-00:00时区偏移量,则将使用客户端的本地时区。您可以将--since选项与--follow选项和/或--tail选项组合使用。

示例:

$ docker logs --since=1m nostalgic_wescoff
172.17.0.1 - - [28/Aug/2021:15:19:24 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.68.0" "-"
172.17.0.1 - - [28/Aug/2021:15:19:25 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.68.0" "-"
$

在上面的示例中,仅显示了过去2分钟的日志,其中nostalgic_wescoff是为nginx容器分配的自动生成的名称。

显示自直到

--since标志类似,docker logs也支持--until标志,它显示给定时间戳之前的日志。类似地,时间戳遵循与前面相似的约定,可以指定为绝对值的语法2021-08-28T15:23:37Z或相对值的语法56m,表示56分钟。

示例:

$ docker logs --until=1h30m nostalgic_wescoff
/docker-entrypoint.sh: /docker-entrypoint.d/不为空,将尝试执行配置
/docker-entrypoint.sh: 在/docker-entrypoint.d/中查找Shell脚本/
/docker-entrypoint.sh: 启动/docker-entrypoint.d/中的10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: 获取/etc/nginx/conf.d/default.conf的校验和
10-listen-on-ipv6-by-default.sh: info: 在/etc/nginx/conf.d/default.conf中启用IPv6侦听
/docker-entrypoint.sh: 启动/docker-entrypoint.d/中的20-envsubst-on-templates.sh
/docker-entrypoint.sh: 启动/docker-entrypoint.d/中的30-tune-worker-processes.sh
/docker-entrypoint.sh: 配置完成;准备启动
2021/08/28 10:29:05 [notice] 1#1: 使用“epoll”事件方法
2021/08/28 10:29:05 [notice] 1#1: nginx/1.21.1
2021/08/28 10:29:05 [notice] 1#1: 编译器版本为gcc 8.3.0(Debian 8.3.0-6)
2021/08/28 10:29:05 [notice] 1#1: 操作系统为Linux 5.8.0-1039-azure
2021/08/28 10:29:05 [notice] 1#1: 获取文件描述符限制(RLIMIT_NOFILE):1048576:1048576
2021/08/28 10:29:05 [notice] 1#1: 启动工作进程
2021/08/28 10:29:05 [notice] 1#1: 启动工作进程33
2021/08/28 10:29:05 [notice] 1#1: 启动工作进程34
172.17.0.1 - - [28/Aug/2021:10:29:26 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.68.0" "-"
$

在上面的示例中,显示了1小时30分钟之前的所有日志。

显示时间戳

许多容器应用程序在其日志输出中内置了时间戳,因此Docker也会在docker logs命令中显示它们。如果您需要Docker在输出中显式添加时间戳前缀,请使用--timestamps-t标志。

示例:

$ docker logs -t redis
2021-08-28T16:53:42.160312570Z 1:C 28 Aug 2021 16:53:42.160 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
2021-08-28T16:53:42.160337871Z 1:C 28 Aug 2021 16:53:42.160 # Redis version=6.2.5, bits=64, commit=00000000, modified=0, pid=1, just started
2021-08-28T16:53:42.160342171Z 1:C 28 Aug 2021 16:53:42.160 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
2021-08-28T16:53:42.160792578Z 1:M 28 Aug 2021 16:53:42.160 * monotonic clock: POSIX clock_gettime
2021-08-28T16:53:42.161148683Z 1:M 28 Aug 2021 16:53:42.161 * Running mode=standalone, port=6379.
2021-08-28T16:53:42.161170984Z 1:M 28 Aug 2021 16:53:42.161 # Server initialized
2021-08-28T16:53:42.161186984Z 1:M 28 Aug 2021 16:53:42.161 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
2021-08-28T16:53:42.161484389Z 1:M 28 Aug 2021 16:53:42.161 * Ready to accept connections
$

合并标志

Docker提供了将某些标志组合以获得更多过滤的输出而不是在屏幕上打印所有日志内容的功能。作为一个简单的示例,我们可以将--tail标志与--since标志组合以获得更受限制的输出。

示例:

$ docker logs --since=2h -f nostalgic_wescoff
172.17.0.1 - - [28/Aug/2021:15:19:24 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.68.0" "-"
172.17.0.1 - - [28/Aug/2021:15:19:25 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.68.0" "-"

这也适用于其他标志。

使用Shell工具过滤

Linux的Shell工具也可以用于更灵活地处理日志输出。可以将grepheadtail等工具与docker logs输出进行管道连接,以进行更高级的操作。

示例:

$ docker logs --since=7h nostalgic_wescoff 2>&1 | grep GET
172.17.0.1 - - [28/Aug/2021:10:29:26 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.68.0" "-"
172.17.0.1 - - [28/Aug/2021:15:19:24 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.68.0" "-"
172.17.0.1 - - [28/Aug/2021:15:19:25 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.68.0" "-"
$

请注意,我们需要重定向日志流以提供单个管道输入,以便使用2>&1将其提供给grep

总结 👩‍💻

Docker是一个多功能的平台,提供了许多功能来管理其环境。管理系统日志是每个系统管理员都应该掌握的基本技能之一。一旦您了解了Docker的可用命令和可能的标志,管理Docker的日志就变得很容易。

有关Docker及其功能的更多阅读材料,请参阅Docker的documentation

类似文章