11进阶:日志与磁盘治理

第 11 关 日志与磁盘治理
本关的产出:知道磁盘被谁吃、容器的日志落在哪、怎么给它设上限,以及为什么「清一遍」不等于解决。
11.1 空间被谁吃了
第 1 关用过 docker system df,现在把它的四行看仔细:
docker system df分别是 镜像、容器、卷、构建缓存。加 -v 能看到每一项具体是谁:
docker system df -v第 1 关只到「怎么看、怎么收」。这一关解决两个问题:这些东西是怎么长起来的,以及为什么随手一清治不了根。
11.2 日志:落在哪,能长多大
先分清两种「日志」——第 1 关提过一次:docker logs 给的是容器里主进程往标准输出(stdout/stderr)写的那点东西,不是 Docker 自己的日志。
这些输出,Docker 会一路接住、存成文件。文件在哪:
docker inspect --format '{{.LogPath}}' <容器>打出来是 /var/lib/docker/containers/<容器ID>/<容器ID>-json.log。docker logs 读的就是它。
要注意的两点:
- 这个路径在「跑 Docker 引擎的那台机器」上,不一定就是你面前这台:Linux 上它就是本机路径,能直接打开(多半要 root);macOS、Windows 上 Docker 跑在虚拟机里,宿主机够不到它。
- 默认没有任何上限。 只要容器在往 stdout 写,这个文件就一直长——一个话多的容器,能把磁盘写满。这是「磁盘莫名被吃掉」最常见的一个来源。
要观察:容器一删,这个文件跟着删(它就在容器的目录底下)。所以 docker system prune 清掉一个已停止的容器时,顺带把它那份日志也清了。
11.3 给它设个上限
不给上限,就只能等它出事。两个地方可以设。
一次性的,写在 run 里:
docker run -d --log-opt max-size=10m --log-opt max-file=3 nginxmax-size 是单个日志文件的上限,max-file 是最多留几个。写满了就轮转——新的进来,最旧的丢掉。
一次设好、全局生效(推荐)。Docker 那个守护进程(第 1 关说的「服务端」)有一份自己的配置文件,叫 daemon.json——它启动时读一遍,里面的设置对所有容器生效。日志上限就写在这儿:
{ "log-driver": "json-file", "log-opts": { "max-size": "10m", "max-file": "3" }}文件在哪,随平台不同:
- Linux:
/etc/docker/daemon.json,直接编辑; - macOS / Windows(Docker Desktop):这文件在它的虚拟机里,不去摸路径——用 Settings → Docker Engine 那个界面改,改的就是同一个文件。
改完重启 Docker 生效。之后每个新容器都自带这套上限。compose 里也可以用 logging: 段设同样两项。
代价要讲清:轮转意味着旧日志会被丢。docker logs 只能看到最后几个文件里的内容。真要长期留,得把日志送到别处(日志系统的活,不在本系列)。
易踩的坑:改 daemon.json 只对新起的容器生效,已经在跑的容器不受影响——要它们也受约束,得重建。
11.4 为什么 prune 治不了根
docker system prune 清的是:已停止的容器、没在用的网络、悬空镜像、构建缓存。它有两个够不着的地方:
- 它不碰正在跑的容器的日志。 日志不在它管的四类里——一个跑着的容器把磁盘写满,
prune一点忙都帮不上。 - 清完很快就长回来。 构建缓存会再攒、匿名卷会再造(第 4 关和第 9 关都点过)、日志会再写。
所以 prune 是扫帚,不是堵源头。真要让空间不出事,靠的是前面几关那些源头上的约束:
- 日志设上限(11.3);
.dockerignore挡掉不该进镜像的东西(第 3 关);RUN里装完就清、清在同一条指令里(第 9 关);- 别随手造匿名卷(第 4 关、第 9 关的
VOLUME)。
错觉:就算清掉了虚拟机里的东西,也不一定立刻还给宿主机。Docker Desktop 那块磁盘镜像(在设置里能看到的那个上限)是只长不缩的。所以 df 里回收了、宿主机的可用空间却没动,别慌——那不是没清掉。
11.5 清一遍
原则是先看清楚再动手,别上来就一把梭。
docker system df -v然后按需要、按类清,每一类各有一条:
docker container prune # 已停止的容器docker image prune # 悬空镜像docker image prune -a # 没被任何容器引用的镜像(更狠)docker network prune # 没在用的网络docker volume prune # 没被使用的卷docker builder prune # 构建缓存一把清:
docker system prune # 容器 / 网络 / 悬空镜像 / 构建缓存docker system prune -a --volumes # 连没用的镜像和卷也清易踩的坑:这些 prune 都不问你,确认都没有了才跑。-a 和 --volumes 尤其要看清——前者把没在用的镜像全删(下次构建得重新拉底),后者会删掉只是暂时没挂载的卷。
这一关的产出:知道磁盘被谁吃、给日志设了上限、也明白清理是扫帚不是根治。下一关反过来——不是空间出了问题,而是服务起不来、连不上,怎么在十分钟内定位到出错的那一层。
本关命令速查
系统清理与日志,见 命令速查表 · 系统与清理。
支持与分享
如果这篇文章对你有帮助,欢迎分享给更多人或打赏支持!





