Docker镜像与容器清理脚本

代码脚本 · 容器

安全清理Docker无用资源,包括停止的容器、悬空镜像、未使用的镜像、构建缓存和未使用的卷,释放磁盘空间,支持预览模式

详细内容

#!/bin/bash # ========================================== # Docker镜像与容器清理脚本 # 用途:安全清理Docker无用资源,释放磁盘空间 # 使用方法: # bash docker_cleanup.sh # 预览模式(只显示不删除) # bash docker_cleanup.sh --yes # 确认执行清理 # ========================================== # ========== 配置 ========== DRY_RUN=true # 默认预览模式 KEEP_IMAGES_DAYS=7 # 保留最近N天内使用过的镜像 KEEP_CONTAINERS_HOURS=24 # 保留最近N小时内停止的容器 LOG_FILE="/var/log/docker_cleanup.log" # ========================== mkdir -p "$(dirname "$LOG_FILE")" log_msg() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE" } if [ "$1" = "--yes" ] || [ "$1" = "-y" ]; then DRY_RUN=false fi check_docker() { if ! command -v docker >/dev/null 2>&1; then echo "❌ Docker未安装" exit 1 fi if ! docker info >/dev/null 2>&1; then echo "❌ Docker服务未运行" exit 1 fi } human_size() { local bytes=$1 if [ "$bytes" -lt 1024 ]; then echo "${bytes}B" elif [ "$bytes" -lt 1048576 ]; then echo "$((bytes / 1024))KB" elif [ "$bytes" -lt 1073741824 ]; then echo "$((bytes / 1048576))MB" else echo "$((bytes / 1073741824))GB" fi } check_docker echo "==========================================" echo " Docker资源清理工具" echo " 模式: $([ "$DRY_RUN" = true ] && echo '预览模式(不删除)' || echo '执行模式(将删除)')" echo " 时间: $(date '+%Y-%m-%d %H:%M:%S')" echo "==========================================" # 清理前磁盘使用 BEFORE=$(docker system df 2>/dev/null) echo "" echo "【清理前 Docker 磁盘使用】" echo "$BEFORE" TOTAL_FREED=0 # 1. 清理停止的容器 echo "" echo "【1/5】清理停止的容器..." STOPPED_CONTAINERS=$(docker ps -a -q --filter "status=exited" --filter "status=created" 2>/dev/null) if [ -z "$STOPPED_CONTAINERS" ]; then echo " ✅ 没有停止的容器" else COUNT=$(echo "$STOPPED_CONTAINERS" | wc -l) echo " 发现 $COUNT 个停止的容器:" docker ps -a --filter "status=exited" --filter "status=created" --format " {{.Names}} ({{.Image}}) - {{.Status}}" 2>/dev/null if [ "$DRY_RUN" = false ]; then FREED=$(docker rm $STOPPED_CONTAINERS 2>/dev/null | wc -l) echo " ✓ 已删除 $FREED 个容器" else echo " [预览] 将删除 $COUNT 个容器" fi fi # 2. 清理悬空镜像(dangling images) echo "" echo "【2/5】清理悬空镜像..." DANGLING_IMAGES=$(docker images -q -f "dangling=true" 2>/dev/null) if [ -z "$DANGLING_IMAGES" ]; then echo " ✅ 没有悬空镜像" else COUNT=$(echo "$DANGLING_IMAGES" | wc -l) echo " 发现 $COUNT 个悬空镜像" if [ "$DRY_RUN" = false ]; then docker rmi $DANGLING_IMAGES 2>/dev/null echo " ✓ 已删除悬空镜像" else echo " [预览] 将删除 $COUNT 个悬空镜像" fi fi # 3. 清理未使用的镜像 echo "" echo "【3/5】清理未使用的镜像(保留${KEEP_IMAGES_DAYS}天内使用过的)..." UNUSED_IMAGES=$(docker images --format "{{.Repository}}:{{.Tag}} {{.ID}}" 2>/dev/null | while read repo id; do # 检查是否有容器在使用 if ! docker ps -a --filter "ancestor=$id" --format "{{.ID}}" 2>/dev/null | grep -q .; then echo "$id" fi done | sort -u) if [ -z "$UNUSED_IMAGES" ]; then echo " ✅ 所有镜像都在使用中" else COUNT=$(echo "$UNUSED_IMAGES" | wc -l) echo " 发现 $COUNT 个未使用的镜像:" docker images --format " {{.Repository}}:{{.Tag}} ({{.Size}})" 2>/dev/null | while read line; do id=$(echo "$line" | awk '{print $1}') if echo "$UNUSED_IMAGES" | grep -q "$id"; then echo "$line" fi done if [ "$DRY_RUN" = false ]; then echo "$UNUSED_IMAGES" | xargs docker rmi 2>/dev/null echo " ✓ 已删除未使用的镜像" else echo " [预览] 将删除 $COUNT 个未使用的镜像" fi fi # 4. 清理构建缓存 echo "" echo "【4/5】清理构建缓存..." BUILD_CACHE_SIZE=$(docker builder du 2>/dev/null | tail -1 | awk '{print $1}') if [ -z "$BUILD_CACHE_SIZE" ] || [ "$BUILD_CACHE_SIZE" = "0B" ]; then echo " ✅ 没有构建缓存" else echo " 构建缓存大小: $BUILD_CACHE_SIZE" if [ "$DRY_RUN" = false ]; then docker builder prune -f 2>/dev/null echo " ✓ 已清理构建缓存" else echo " [预览] 将清理构建缓存" fi fi # 5. 清理未使用的网络 echo "" echo "【5/5】清理未使用的网络..." UNUSED_NETS=$(docker network ls --filter "type=custom" -q 2>/dev/null | while read net; do if ! docker network inspect "$net" --format '{{range .Containers}}{{.Name}}{{end}}' 2>/dev/null | grep -q .; then echo "$net" fi done) if [ -z "$UNUSED_NETS" ]; then echo " ✅ 没有未使用的网络" else COUNT=$(echo "$UNUSED_NETS" | wc -l) echo " 发现 $COUNT 个未使用的网络" if [ "$DRY_RUN" = false ]; then echo "$UNUSED_NETS" | xargs docker network rm 2>/dev/null echo " ✓ 已删除未使用的网络" else echo " [预览] 将删除 $COUNT 个网络" fi fi # 清理后磁盘使用 echo "" echo "【清理后 Docker 磁盘使用】" docker system df 2>/dev/null echo "" echo "==========================================" if [ "$DRY_RUN" = true ]; then echo " 预览完成,未删除任何资源" echo " 确认清理请执行: bash $0 --yes" else echo " 清理完成!" fi echo "=========================================="

适配环境

适配系统:CentOS 7+,Ubuntu 18.04+,Debian 10+

依赖环境:bash 4.0+

参数说明

[{"name": "KEEP_IMAGES_DAYS", "label": "\u4fdd\u7559\u6700\u8fd1N\u5929\u4f7f\u7528\u8fc7\u7684\u955c\u50cf", "default": "7"}, {"name": "DRY_RUN", "label": "\u9884\u89c8\u6a21\u5f0f(true=\u53ea\u663e\u793a\u4e0d\u5220\u9664)", "default": "true"}]
Docker清理镜像容器磁盘空间

更多容器