原文链接: 被 Docker 日志坑惨了
最近在读《计算机程序的结构和解释》,外面有一句话:代码必须可能被人浏览,只是机器凑巧能够执行。
我也想到了一句话:BUG 肯定可能被人写出,只是恰好我写的多而已。
说多了都是泪,来看看我最近遇到的一个问题。
问题
一般的一天,关上一般的电脑,登录一台一般的服务器,敲下一条一般的命令。
在我应用命令补全时,呈现了一条不一般的提醒:
-bash: cannot create temp file for here-document: No space left on device ls -bash
怎么磁盘满了?
应用 df -h
一看还真是。
什么起因呢?
解决
首先,查找一下零碎里的大文件,看看是哪个小可爱搞的鬼。
du -sh /* | grep G
很快就定位到了这个目录:/var/lib/docker/containers
。
原来是 Docker 这家伙,这个目录下寄存的都是容器运行过程中产生的日志。
应用上面命令来给这些文件按大小排个序:
du -d1 -h /var/lib/docker/containers | sort -h
32K /var/lib/docker/containers/d607c06e475191fff1abd0c2b4b672e7fe8a96cb197f4e8557b18600de2e60af
36K /var/lib/docker/containers/0d4321106721b9d26335fefef7b9e8e23629691684a4da2f953ac8223c8240c3
36K /var/lib/docker/containers/7525aab4aa917aa1016169114762261726ac7b9cc712bef35cdc7035b50d20ce
36K /var/lib/docker/containers/9252e1c373d59ef5613c2b6122eb6e43aa2bd822bd2c199aa67d6eb659c4adb7
142M /var/lib/docker/containers
142M /var/lib/docker/containers/15700ee92cd2831554b9a1e78127df0f07248c1498d35c17525407bc8a98bc1a
文件名称就是容器 ID,每个文件对应一个容器,也就能够定位到,具体是哪个容器产生了大量的日志。
应用这个命令能够将大文件疾速清空:
sh -c "cat /dev/null > ${log_file_name}"
然而清空了文件哪算解决问题,新的日志还在源源不断往日志里打呢。看了看日志内容,很相熟。前两天为了调试程序,刚加的一条 print
。
编辑代码,删除 print
,重启容器。好了,日志不再疯狂追加了。
为什么 print
语句将日志都输入到文件里了呢?别着急,前面再来具体介绍。
先解决一下眼前的问题,放任日志有限增长是必定不行的,须要有一个单个文件大小限度。否则,今天张三再加一条 print
,磁盘又满了。
这里有两个计划:
- 繁多容器配置
- 全局配置
繁多容器配置
启动容器时,通过参数来管制日志的文件个数和单个文件的大小:
docker run -it --log-opt max-size=10m --log-opt max-file=3 redis
但这样做是比拟麻烦的,更多的采纳的是全局配置的形式。
全局配置
编辑 /etc/docker/daemon.json
:
{
"log-driver":"json-file",
"log-opts":{
"max-size" :"50m",
"max-file":"3"
}
}
重启 Docker 服务:
systemctl daemon-reload
systemctl restart docker
留神: 已存在的容器不会失效,须要重建才能够。
接下来再说说上文提到的 print
问题。
Docker 日志
Docker 日志分为两类:
- Docker 引擎日志(也就是 dockerd 运行时的日志)
- 容器的日志,容器内的服务产生的日志
引擎日志
Docker 引擎日志个别是交给了 Upstart(Ubuntu 14.04) 或者 systemd (CentOS 7, Ubuntu 16.04)。前者个别位于 /var/log/upstart/docker.log 下,后者个别通过 journalctl -u docker
进行查看。
不同零碎的地位都不一样,网上有人总结了一份列表,我修改了一下,能够参考:
零碎 | 日志地位 |
---|---|
Ubuntu(14.04) | /var/log/upstart/docker.log |
Ubuntu(16.04) | journalctl -u docker.service |
CentOS 7/RHEL 7/Fedora | journalctl -u docker.service |
CoreOS | journalctl -u docker.service |
OpenSuSE | journalctl -u docker.service |
OSX | ~/Library/Containers/com.docker.docker/Data/com.docker.driver.amd64- |
Debian GNU/Linux 7 | /var/log/daemon.log |
Debian GNU/Linux 8 | journalctl -u docker.service |
Boot2Docker | /var/log/docker.log |
容器日志
应用上面命令能够显示以后运行的容器的日志信息:
docker logs CONTAINER
UNIX 和 Linux 命令有三种输入输出,别离是 STDIN、STDOUT 和 STDERR。docker logs
显示的内容蕴含 STDOUT 和 STDERR。
在生产环境下,如果咱们的利用输入到日志文件里,那么咱们在应用 docker logs
时个别收集不到太多重要的信息。
这里来看一下 nginx 和 httpd 是怎么做的:
- nginx 官网镜像,应用了一种形式,让日志输入到 STDOUT,也就是创立一个符号链接 /var/log/nginx/access.log 到 /dev/stdout。
- httpd 应用的是让其输入到指定文件,失常日志输入到 /proc/self/fd/1 (STDOUT),谬误日志输入到 /proc/self/fd/2 (STDERR)。
当日志量比拟大的时候,应用 docker logs
来查看日志,会对 docker daemon 造成比拟大的压力,容易导致容器创立慢等一系列问题。
只有应用了 local、json-file、journald 日志驱动的容器才能够应用 docker logs
捕捉日志,应用其余日志驱动无奈应用 docker logs
。
Docker 默认应用 json-file 作为日志驱动。
除此之外,Docker 还提供了很多其余日志驱动,这里就不过多介绍。还有日志治理计划,我也不是很有教训,大家如果感兴趣的话本人搜搜看吧。
参考文章:
- https://www.cnblogs.com/zhang…
- https://www.cnblogs.com/opera…
文章中的脑图和源码都上传到了 GitHub,有须要的同学可自行下载。
地址: https://github.com/yongxinz/tech-blog
Go 专栏文章列表:
- Go 专栏|开发环境搭建以及开发工具 VS Code 配置
- Go 专栏|变量和常量的申明与赋值
- Go 专栏|根底数据类型:整数、浮点数、复数、布尔值和字符串
- Go 专栏|复合数据类型:数组和切片 slice
- Go 专栏|复合数据类型:字典 map 和 构造体 struct
- Go 专栏|流程管制,一网打尽
- Go 专栏|函数那些事
- Go 专栏|错误处理:defer,panic 和 recover
- Go 专栏|说说办法
- Go 专栏|接口 interface
- Go 专栏|并发编程:goroutine,channel 和 sync