云服务器40G系统盘频繁告急?记录我排查Docker吃光磁盘的3个隐形元凶
自己平时在华为云上租了一台入门配置的主机,系统盘买的是标准的40G。上面跑的东西也不算多:一个个人博客、一个自建的Gitea代码仓库、一个PostgreSQL数据库,外加两三个自己写的小采集脚本,全是用Docker拉起来跑的。
本来觉得40G应付这点小业务绰绰有余,结果上周末手机突然收到了华为云发来的资源告警短信,提示系统盘使用率已经超过90%。还没等我来得及看,下午几个网页就直接报错500了,连进服务器一查,MySQL由于写不进binlog直接原地停摆,系统盘显示完全吃满,可用空间只剩几百KB。
当时第一反应是我的数据库是不是被人灌垃圾数据了,但导出看了眼业务数据加起来也就一两个G。顺着用du命令一层层排查,最后发现问题全出在/var/lib/docker这个目录下,它自己不声不响吞掉了将近30G的空间。花了大半天排查清理并做好了防范,把这次踩坑的几个具体隐患记下来。
第一个元凶:容器控制台日志默认不设上限,单文件飙到十几个G。
很多用Docker的新手最容易忽略的一点,就是容器向标准输出(stdout)打印的日志,Docker默认会全部以JSON格式写到本地磁盘上,并且默认没有单文件大小限制,也没有文件分割轮转。
我那个爬虫脚本为了方便平时用docker logs排查问题,控制台打日志打得特别勤,抓一条信息就print一行。这个容器不知不觉跑了半年多,去到containers目录下翻看才发现,光是这一个容器的*-json.log文件,体积就整整占了14G。
清理掉这块大头并不难,一条truncate命令清空文件就能立刻腾出空间。但要根治必须修改Docker全局配置。在/etc/docker/daemon.json里加上log-driver和log-opts配置,强制全局单日志文件最大不超过50m,最多保留3个历史轮转文件。配上这个硬性规则并重启Docker服务后,以后不管什么容器再疯狂打日志,最多也就吃150M空间,彻底消除了日志撑爆磁盘的隐患。
第二个元凶:频繁本地构建留下的BuildKit缓存与无标签虚悬镜像。
因为服务器上跑着自己写的小工具,每次代码更新后,我习惯直接在服务器上敲docker build重新打镜像发版。
时间一长,这里面藏了两个容易忽略的垃圾堆:
一是每次重新构建新镜像后,旧镜像的Tag被剥离,变成了仓库名和Tag都显示为none的虚悬镜像(Dangling Images)。这些镜像不仅毫无用处,还占据着好几个G的底层分层文件。
二是Docker构建引擎默认保留的构建缓存(Build Cache)。虽然缓存能让下次打包变快,但对于小规格服务器来说,里面沉积的一堆老旧环境依赖简直是磁盘刺客。
用docker system df一查,光构建缓存就占了快8G。处理方式是在平时的更新脚本里加上定期的清理动作,用docker builder prune定期回收超过时效的构建缓存,结合docker image prune清理掉无用的none镜像,一下子又省出了一大片空间。
第三个元凶:每次更新不小心堆积的匿名数据卷。
用Docker Compose管理服务时,有些镜像(比如数据库或者缓存组件)在Dockerfile内部默认声明了VOLUME挂载点。
如果我们在编写docker-compose.yml时,没有显式给它指定本地的宿主机映射路径(比如./data:/var/lib/mysql),Docker就会在启动时自动给它分配一个以长字符串哈希命名的“匿名数据卷”。
每次只要遇到配置调整需要down掉容器并重新拉起时,旧的匿名卷并不会自动随容器删除,而是默默变成孤儿卷躺在/var/lib/docker/volumes目录里。日积月累,里面甚至留着半年前做测试时遗留下来的旧数据。
用docker volume ls -qf dangling=true扫了一圈,机器上居然飘着十几个毫无关联的匿名卷。把这些僵死数据卷批量干掉后,整个磁盘瞬间清爽了不少。
第四个顺手的安全防范:把临时目录和关键数据抽离出系统盘。
折腾完这次磁盘危机后,我顺便把排错脚本也做成了定时任务。在crontab里加了一条每周日夜间自动执行系统级瘦身的命令,自动清理停止超过24小时的容器和无主网络。
同时给华为云的云监控服务(CES)加上了一条自定义告警规则:当系统盘使用率再次达到80%时就给我推邮件,提前预警,避免非要等到磁盘彻底耗尽、应用报崩才后知后觉地去救火。
现在这台40G的云主机系统盘常年稳定在45%左右的水位,几个业务容器跑得非常安稳。对于资源紧张的个人开发者来说,容器技术确实极大方便了项目部署,但不能把它当成全自动垃圾桶,尽早把全局日志限制锁死,养成定期清理缓存和悬空资源的习惯,才能防止服务器在半夜因为一块小小的日志文件突然暴毙。
- 点赞
- 收藏
- 关注作者
评论(0)