别再只会用`docker system prune`了!聊聊Docker磁盘清理的5个隐藏场景与实战命令
别再只会用docker system prune了!聊聊Docker磁盘清理的5个隐藏场景与实战命令
Docker作为现代开发与运维的核心工具,其便捷性背后往往隐藏着磁盘管理的复杂性。当docker system prune成为大多数人的清理"万能药"时,真正棘手的磁盘问题却常常出现在那些未被充分讨论的角落——容器日志的失控增长、overlay2目录的神秘膨胀、构建缓存的隐形堆积……这些场景需要的不是一刀切的清理,而是精准的手术刀式操作。
1. 容器日志轮转:从根源解决/var/lib/docker/containers爆满问题
当df -h显示/var分区即将爆满时,/var/lib/docker/containers往往是罪魁祸首。默认情况下,Docker容器会将所有标准输出日志以JSON格式存储在此目录,且没有自动轮转机制。我曾见过一个生产环境的Nginx容器在三个月内产生了47GB的日志文件。
1.1 即时清理与日志定位
首先用以下命令快速定位磁盘占用最高的容器日志:
du -d 1 -h /var/lib/docker/containers/ | sort -h
找到目标容器ID后,可以临时清空日志文件(注意:这会丢失所有历史日志):
truncate -s 0 /var/lib/docker/containers/<container_id>/<container_id>-json.log
1.2 配置日志轮转策略
更专业的做法是在容器启动时配置日志驱动和轮转参数:
docker run --log-driver json-file \
--log-opt max-size=100m \
--log-opt max-file=3 \
nginx
关键参数说明:
max-size:单个日志文件最大尺寸(支持k,m,g单位)max-file:保留的历史日志文件数量
对于已运行的容器,修改/etc/docker/daemon.json全局配置并重启Docker服务:
{
"log-driver": "json-file",
"log-opts": {
"max-size": "100m",
"max-file": "3"
}
}
提示:修改全局配置会影响所有新创建的容器,已存在的容器需要重建才能生效
2. 解剖overlay2:读写层异常增长的诊断与修复
Docker存储驱动采用的overlay2文件系统,会在/var/lib/docker/overlay2下为每个容器创建读写层(merged目录)。当这些目录异常增长时,常规清理往往无效。
2.1 定位问题容器
使用以下命令查看各容器占用的磁盘空间(包括读写层):
docker ps -s --format "table {{.ID}}\t{{.Names}}\t{{.Size}}"
输出示例:
CONTAINER ID NAMES SIZE
a1b2c3d4e5f6 mysql_db 2.45GB (virtual 1.2GB)
其中"SIZE"列显示的是读写层大小,"(virtual)"表示镜像基础大小。
2.2 深入分析具体容器
对可疑容器进行深入检查:
docker exec -it <container_id> bash -c "du -h --max-depth=1 / | sort -h"
常见问题根源:
- 应用程序生成的临时文件未清理
- 数据库未配置自动清理(如MySQL的binlog)
- 上传目录缺乏定期清理机制
2.3 针对性清理方案
对于MySQL容器,可以设置自动清理binlog:
SET GLOBAL expire_logs_days = 3;
对于临时文件问题,建议在Dockerfile中加入清理指令:
RUN apt-get update && \
apt-get install -y package && \
rm -rf /var/lib/apt/lists/*
3. 构建缓存管理:超越docker builder prune的精细控制
Docker构建缓存虽然加速了构建过程,但长期积累会占用大量空间。docker builder prune虽然简单,但缺乏针对性。
3.1 查看缓存详细组成
docker builder du --verbose
输出示例:
Build Cache: 5.7GB
- 3.2GB FROM alpine:latest
- 1.1GB RUN apk add --no-cache python3
- 0.8GB COPY . /app
- 0.6GB RUN pip install -r requirements.txt
3.2 精准清理特定缓存层
保留基础镜像缓存,仅清理应用层:
docker builder prune --filter type=exec.cachemount
可选过滤器:
type=regular:常规Dockerfile指令产生的缓存type=internal:内部使用的缓存type=source.local:本地源文件缓存
3.3 构建时控制缓存行为
在Dockerfile中合理使用--mount=type=cache:
RUN --mount=type=cache,target=/var/cache/apt \
apt-get update && \
apt-get install -y build-essential
这样既保持了构建速度,又避免了缓存污染主镜像。
4. 镜像深度清理:区分悬空镜像与中间层
docker image prune默认只清理悬空镜像(dangling images),但中间层(intermediate layers)才是真正的空间杀手。
4.1 识别不同类型的镜像
docker images -a --filter dangling=true # 悬空镜像
docker images -a --format "{{.ID}}\t{{.CreatedSince}}\t{{.Size}}" | sort -k2 -h
4.2 安全清理中间层
先查看可清理的空间预估:
docker system df -v
然后使用带过滤器的清理命令:
docker image prune -a --filter "until=24h" # 清理24小时前的未使用镜像
4.3 保留关键镜像的策略
给重要镜像打上保留标签:
docker tag my_image:latest my_image:keep
这样在执行prune时可以通过--filter排除:
docker image prune -a --filter="label!=keep"
5. 自动化清理:安全可靠的crontab方案
手动清理终究不是长久之计,但自动化清理需要特别注意安全性。
5.1 基础清理脚本
创建/usr/local/bin/docker-cleanup:
#!/bin/bash
# 清理超过7天的已停止容器
docker container prune --force --filter "until=168h"
# 清理未使用的镜像(保留最近3个版本)
docker image prune -a --force --filter "until=72h"
# 清理构建缓存
docker builder prune --force --filter "until=24h"
# 清理网络和卷
docker network prune --force
docker volume prune --force
5.2 安全增强措施
添加资源使用限制和日志记录:
#!/bin/bash
LOG_FILE="/var/log/docker-cleanup.log"
MAX_DISK_USAGE=90
current_usage=$(df -h /var/lib/docker | awk 'NR==2 {print $5}' | tr -d '%')
if [ "$current_usage" -lt "$MAX_DISK_USAGE" ]; then
echo "$(date) - Disk usage ${current_usage}% below threshold. Skipping cleanup." >> "$LOG_FILE"
exit 0
fi
echo "$(date) - Starting cleanup (Current usage: ${current_usage}%)" >> "$LOG_FILE"
# ...原有清理命令...
5.3 设置crontab定时任务
sudo crontab -e
添加以下内容(每天凌晨3点执行,且磁盘使用超过85%时):
0 3 * * * /usr/local/bin/docker-cleanup
注意:避免在业务高峰期执行清理,特别是生产环境
更多推荐
所有评论(0)