#!/bin/bash # 生产环境Docker镜像瘦身脚本 # 用途:安全清理未使用的Docker镜像 set -e # 颜色定义 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # 日志函数 log_info() { echo -e "${BLUE}[INFO]${NC} $1" } log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1" } log_warning() { echo -e "${YELLOW}[WARNING]${NC} $1" } log_error() { echo -e "${RED}[ERROR]${NC} $1" } separator() { echo "======================================================================" } # 记录日志 LOG_FILE="/tmp/docker-cleanup-$(date +%Y%m%d_%H%M%S).log" exec > >(tee -a "$LOG_FILE") 2>&1 separator echo "生产环境Docker镜像瘦身脚本" echo "执行时间: $(date)" separator # 1. 显示当前状态 log_info "步骤1: 当前Docker资源使用情况" separator echo "" docker system df echo "" log_info "当前镜像列表:" docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}\t{{.CreatedSince}}" echo "" log_info "运行中的容器:" docker ps --format "table {{.Names}}\t{{.Image}}\t{{.Status}}" # 2. 分析未使用的镜像 separator log_info "步骤2: 分析未使用的镜像" separator echo "" log_info "悬空镜像(标签):" DANGLING_IMAGES=$(docker images -f "dangling=true" -q) if [ -n "$DANGLING_IMAGES" ]; then docker images -f "dangling=true" --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}\t{{.CreatedSince}}" DANGLING_SIZE=$(docker images -f "dangling=true" --format "{{.Size}}" | grep -oE '[0-9.]+[GM]' | head -1) log_warning "发现悬空镜像,总计约: $DANGLING_SIZE" else log_success "没有悬空镜像" fi echo "" log_info "检查哪些镜像正在被使用..." RUNNING_IMAGES=$(docker ps --format "{{.Image}}" | sort -u) log_info "正在使用的镜像:" echo "$RUNNING_IMAGES" echo "" log_info "未被容器使用的镜像:" docker images --format "{{.Repository}}:{{.Tag}}" | while read image; do if ! echo "$RUNNING_IMAGES" | grep -q "$(echo $image | cut -d: -f1)"; then echo "$image" fi done # 3. 清理悬空镜像(安全) separator log_info "步骤3: 清理悬空镜像" separator if [ -n "$DANGLING_IMAGES" ]; then log_warning "将删除以下悬空镜像:" docker images -f "dangling=true" --format "{{.ID}}\t{{.Size}}" echo "" read -p "确认删除悬空镜像?(y/n): " -n 1 -r echo if [[ $REPLY =~ ^[Yy]$ ]]; then log_info "正在清理悬空镜像..." docker image prune -f log_success "悬空镜像清理完成" else log_info "跳过悬空镜像清理" fi else log_success "没有悬空镜像需要清理" fi # 4. 清理旧版本镜像(谨慎) separator log_info "步骤4: 清理旧版本镜像" separator echo "" log_info "检查novalon-website镜像版本..." NOVALON_IMAGES=$(docker images "novalon-website" --format "{{.Tag}}\t{{.Size}}\t{{.CreatedSince}}") echo "$NOVALON_IMAGES" echo "" log_info "当前使用的版本:" docker ps --filter "name=novalon-website" --format "{{.Image}}" # 检查是否有旧版本 OLD_VERSIONS=$(docker images "novalon-website" --format "{{.Tag}}" | grep -v "latest" | head -n -1) if [ -n "$OLD_VERSIONS" ]; then log_warning "发现旧版本镜像:" echo "$OLD_VERSIONS" echo "" read -p "是否删除旧版本镜像?(y/n): " -n 1 -r echo if [[ $REPLY =~ ^[Yy]$ ]]; then for version in $OLD_VERSIONS; do log_info "删除镜像: novalon-website:$version" docker rmi "novalon-website:$version" || log_warning "无法删除 novalon-website:$version(可能正在使用)" done log_success "旧版本镜像清理完成" else log_info "跳过旧版本镜像清理" fi else log_success "没有旧版本镜像需要清理" fi # 5. 清理构建缓存 separator log_info "步骤5: 清理构建缓存" separator CACHE_SIZE=$(docker system df | grep "Build Cache" | awk '{print $3}') log_info "构建缓存大小: $CACHE_SIZE" if [ "$CACHE_SIZE" != "0B" ]; then read -p "是否清理构建缓存?(y/n): " -n 1 -r echo if [[ $REPLY =~ ^[Yy]$ ]]; then log_info "正在清理构建缓存..." docker builder prune -a -f log_success "构建缓存清理完成" else log_info "跳过构建缓存清理" fi else log_success "没有构建缓存需要清理" fi # 6. 清理未使用的卷(可选) separator log_info "步骤6: 清理未使用的卷(可选)" separator UNUSED_VOLUMES=$(docker volume ls -q --filter "dangling=true") if [ -n "$UNUSED_VOLUMES" ]; then log_warning "发现未使用的卷:" echo "$UNUSED_VOLUMES" read -p "是否清理未使用的卷?(y/n): " -n 1 -r echo if [[ $REPLY =~ ^[Yy]$ ]]; then log_info "正在清理未使用的卷..." docker volume prune -f log_success "未使用卷清理完成" else log_info "跳过未使用卷清理" fi else log_success "没有未使用的卷" fi # 7. 显示清理结果 separator log_info "步骤7: 清理结果" separator echo "" log_info "清理后的Docker资源使用情况:" docker system df echo "" log_info "磁盘空间变化:" df -h | grep -E "Filesystem|/$" separator log_success "Docker镜像瘦身完成" separator echo "" log_info "清理摘要:" echo " ✅ 悬空镜像已清理" echo " ✅ 旧版本镜像已清理" echo " ✅ 构建缓存已清理" echo " ✅ 未使用卷已清理" echo "" log_info "详细日志已保存到: $LOG_FILE" echo "" log_warning "建议后续操作:" echo " 1. 监控服务状态: docker ps" echo " 2. 验证应用访问: curl -I https://novalon.cn" echo " 3. 设置定期清理: crontab -e" echo " 4. 配置日志轮转: /etc/logrotate.d/docker" separator