接上文 Linux服务器磁盘占用分析和清理 ,根据最终的分析结果,发现目前我的服务器中,磁盘占用的主要原因是Docker存储(overlay2)。
所以就有了这篇分析 docker 使用和清理的文章。
docker system df
输出示例:
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 10 5 12.5GB 7.5GB (60%)
Containers 8 3 8.2GB 5.1GB (62%)
Local Volumes 5 2 3.7GB 1.2GB (32%)
Build Cache 0 0 0B 0B
# 查看容器占用
docker ps -s
# 查看镜像占用(按大小排序)
docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}" | sort -k3 -h -r
# 查看所有Docker对象占用
docker stats --all --no-stream
# 查看所有已停止的容器
docker ps -a --filter "status=exited" --filter "status=created"
# 删除已停止的容器(谨慎操作)
docker container prune
# 删除特定条件的容器(如创建时间超过30天)
docker container prune --filter "until=720h"
# 删除悬挂镜像(没有标签的镜像)
docker image prune
# 删除所有未被容器使用的镜像
docker image prune -a
# 删除特定时间前的镜像
docker image prune -a --filter "until=168h" # 7天前
# 查看未被容器使用的卷
docker volume ls -f dangling=true
# 删除未被使用的卷
docker volume prune
# 删除特定条件的卷
docker volume prune --filter "label!=keep"
# 清理构建缓存
docker builder prune
# 清理所有构建缓存
docker builder prune -a
创建 /usr/local/bin/docker-cleanup.sh:
#!/bin/bash
echo "=== Docker磁盘清理开始 ==="
echo "当前磁盘使用情况:"
df -h /
echo -e "\n=== Docker磁盘使用统计 ==="
docker system df
echo -e "\n=== 1. 清理已停止的容器 ==="
docker container prune --force
echo -e "\n=== 2. 清理悬挂镜像 ==="
docker image prune --force
echo -e "\n=== 3. 清理未使用的卷 ==="
docker volume prune --force
echo -e "\n=== 4. 清理构建缓存 ==="
docker builder prune --force
echo -e "\n=== 清理后的Docker状态 ==="
docker system df
echo -e "\n=== 最终磁盘使用情况 ==="
df -h /
echo "=== Docker磁盘清理完成 ==="
设置权限:
sudo chmod +x /usr/local/bin/docker-cleanup.sh
# 查看overlay2目录大小
sudo du -sh /var/lib/docker/overlay2
# 查看各子目录大小
sudo du -sh /var/lib/docker/overlay2/* | sort -rh | head -20
# 首先停止所有容器
docker stop $(docker ps -q)
# 备份重要的容器数据
# 如果有需要持久化的数据,请确保已备份
# 重启Docker服务(有时可以释放一些空间)
sudo systemctl restart docker
# 重新运行清理命令
docker system prune -a --volumes
# 查看Docker容器日志大小
for container in $(docker ps -aq); do
echo "容器 $(docker inspect --format='{{.Name}}' $container) 日志大小:"
docker inspect --format='{{.LogPath}}' $container | xargs sudo du -h 2>/dev/null || echo "无日志"
done
# 清理所有容器的日志(不影响正在运行的容器)
truncate -s 0 /var/lib/docker/containers/*/*-json.log
编辑或创建 /etc/docker/daemon.json:
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
},
"storage-driver": "overlay2",
"storage-opts": [
"overlay2.override_kernel_check=true"
]
}
应用配置:
sudo systemctl daemon-reload
sudo systemctl restart docker
创建定时任务 /etc/cron.daily/docker-cleanup:
#!/bin/bash
docker system prune -f
docker volume prune -f
设置权限:
sudo chmod +x /etc/cron.daily/docker-cleanup
创建监控脚本 /usr/local/bin/docker-monitor.sh:
#!/bin/bash
THRESHOLD=80
CURRENT=$(df / --output=pcent | tail -1 | tr -d '% ')
if [ $CURRENT -gt $THRESHOLD ]; then
echo "警告:磁盘使用率超过${THRESHOLD}%(当前:${CURRENT}%)"
echo "Docker占用详情:"
docker system df
# 可以添加自动清理逻辑
fi
# 查看哪些镜像正在被使用
docker images --no-trunc | grep -v "<none>" | awk '{print $3}' | xargs docker inspect --format='{{.Id}} {{.RepoTags}}' 2>/dev/null
# 查看所有运行中的容器及其镜像
docker ps --format "table {{.Names}}\t{{.Image}}\t{{.Status}}"
# 备份容器数据卷
for container in $(docker ps -q); do
docker inspect --format='{{range .Mounts}}{{.Source}} {{end}}' $container | while read volume; do
if [ ! -z "$volume" ]; then
echo "备份容器 $container 的卷: $volume"
tar -czf /backup/container_${container}_$(date +%Y%m%d).tar.gz $volume
fi
done
done
# 给重要容器添加标签防止被清理
docker update --label keep=true <container_name_or_id>
# 给重要镜像添加标签
docker tag <image_id> important-image:latest
按照以下顺序安全清理:
执行清理命令:
# 安全清理(交互式)
docker system prune
# 强制清理(非交互式)
sudo /usr/local/bin/docker-cleanup.sh
# 查看清理效果
docker system df
df -h /
最后,提醒一定要慎重、慎重清理啊。