深入Docker容器之日志篇
操作系统流重定向
在linux系统中,运行一个命令,通常会是以下的方式:

在linux 和 Unix系统中,在运行程序时,通常会有三种io流: stdin, stdout,stderr 。 stdin 是从外部设备或是键盘获取输入,而 stdout 是标准输出,stderr 是标准错误输出。而不管是标准输出和标准错误输出都是默认输出至显示器上的,对于信息查看是很乱的,在linux中数据流重定向,可以将不同的标准输出到指定的文件中。
在linux中不同的数据流有特定的文件描述符来表示:
- 标准输入(/dev/stdin) -> 文件描述符为 0 ,使用 < 或是 <<(其中<是从设备获取输入,<< 结束输入字符)
- 标准输出(/dev/stdout) -> 文件描述符为 1 ,使用 > 或 >>(其中> 是覆盖方式输出,>> 是追加方式输出)
- 标准错误输出(/dev/stderr) -> 文件描述符为 2 使用 2> 或是 2>>(其中> 是覆盖方式输出,>> 是追加方式输出)
使用方式:
M>N : M 是文件描述符,默认是1 ,N 是文件名称
M>&N : M是文件描述符,默认是1,N是引用另一个文件描述符
示例:
- 重定向错误输出流
[root@master ~]# ll /home/user1 =》 1
ls: 无法访问/home/user1: 没有那个文件或目录 # 默认stderr & stdout都显示在屏幕
[root@master ~]# ll /home/user1 > 1.log 2>2.log =》2
[root@master ~]#
[root@master ~]# ll /home/user1 > 1.log 2>&1 =》 3
在上面的示例中,默认stderr 和 stdout都是显示在屏幕上,第二句执行后,屏幕未显示内容,是因为通过流重定向,将内容输出到指定的文件上,而第三句是将错误信息和标准输出统一都输出在同一个文件1.log。
Docker日志配置
理解了系统层面的数据流原理,那再来看docker的日志输出,应该会比较容易理解。
默认,docker logs 只显示容器的标准输出和标准错误输出,和你在终端执行命令没有什么区别。docker内部也是通过数据流重定向来指定输出的,也只会显示stdout 和 stderr的内容。
来看下 nginx的官方Dockerfile,这里做了一个软链接,将 /dev/stdout ->/var/log/nginx/access.log
# forward request and error logs to docker log collector
RUN ln -sf /dev/stdout /var/log/nginx/access.log \
&& ln -sf /dev/stderr /var/log/nginx/error.log
这样在使用docker logs 时,就可以看到访问日志和错误日志了。
docker日志驱动配置
docker的日志驱动,默认是 json-file的方式,以json的格式输出,格式如下:
{"log":"Log line is here\n","stream":"stdout","time":"2019-01-01T11:11:11.111111111Z"}
目录在 /var/lib/docker/containers/{dockerId}/{dockerId}.json.log
可以通过配置 /etc/docker/daemon.json 文件调整日志,如
{
"log-driver": "json-file", # 指定日志支持的格式
"log-opts": {
"max-size": "10m", # 产生的文件最大存储
"max-file": "3" # 经过日志切割后保留的最大文件,超过的会删除
}
}
在重启docker服务后,以上配置会影响当前宿主机之后创建的新的容器,旧的容器不影响,除非是重新创建容器。
也可以在创建容器时,通过指定参数来为容器调整日志配置
docker run \
--log-driver local --log-opt max-size=10m --log-opt max-file=3 \
alpine echo hello world
--log-driver 指定日志的输出格式
--log-opt 指定log 的选项,如指定日志切割的配置
docker 支持的日志驱动格式
格式 | 说明 |
none | 不输出任何内容 |
local | 以自定义格式存储,是为了最小化开销 |
syslog | 日志写入 syslog工具,syslogd守护进程必须在主机上运行 |
journald | 日志写入 journald,journald守护进程必须在主机上运行 |
gelf | 日志写入 GELF终端 |
fluentd | 日志写入fluentd,fluentd守护进程必须在主机上运行 |
json-file | 日志格式化为 json, 这是docker默认的日志驱动程序 |
awslogs | 日志写入Amazon CloudWatch Logs |
splunk | 使用http事件收集器将日志写入spunk |
etwlogs | 日志写入windows的event tracing事件 |
gcplogs | 日志写入 Google Cloud Platform Logging |