Docker 容器磁盘清理
问题: /var/lib/docker/containers/ 文件过大
在这里插入图片描述# Docker 容器磁盘清理指南

问题分析

/var/lib/docker/containers 目录中有容器占用了大量空间:

  • 181G: 5ae1c9345a6e6da0ece25698f6214a90b874417ba61b2e61f2af0413a844bb02
  • 15G: e433a85edaaea86855c6518397c388f88493714ee073f370d270e4e3b118f7f0

这些大文件通常是容器的日志文件(*-json.log)导致的。

快速解决方案

方法 1: 使用清理脚本(推荐)

  1. cleanup_docker_containers.sh - 交互式清理脚本
    提供菜单选择不同清理选项
    可查看占用空间最大的容器
    支持清理日志、已停止容器、未使用数据等
#!/bin/bash

# Docker 容器清理脚本
# 用于降低 /var/lib/docker/containers 目录的磁盘使用量

set -e

echo "=========================================="
echo "Docker 容器磁盘清理脚本"
echo "=========================================="
echo ""

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

# 检查是否为 root 用户
if [ "$EUID" -ne 0 ]; then 
    echo -e "${RED}错误: 请使用 root 权限运行此脚本${NC}"
    exit 1
fi

# 显示当前磁盘使用情况
echo -e "${YELLOW}当前容器目录磁盘使用情况:${NC}"
du -sh /var/lib/docker/containers/* 2>/dev/null | sort -hr | head -10
echo ""

# 函数:显示磁盘使用前 N 个容器
show_top_containers() {
    echo -e "${YELLOW}占用空间最大的容器:${NC}"
    du -sh /var/lib/docker/containers/* 2>/dev/null | sort -hr | head -5
    echo ""
}

# 函数:清理容器日志文件
cleanup_logs() {
    echo -e "${YELLOW}开始清理容器日志文件...${NC}"
    
    # 查找所有容器的日志文件
    find /var/lib/docker/containers/ -name "*-json.log" -type f | while read logfile; do
        container_id=$(basename $(dirname $logfile))
        log_size=$(du -sh "$logfile" | cut -f1)
        echo "  清理日志: $container_id ($log_size)"
        
        # 清空日志文件(保留文件但清空内容)
        > "$logfile"
    done
    
    echo -e "${GREEN}日志文件清理完成${NC}"
    echo ""
}

# 函数:清理已停止的容器
cleanup_stopped_containers() {
    echo -e "${YELLOW}开始清理已停止的容器...${NC}"
    
    # 获取已停止的容器
    stopped_containers=$(docker ps -a -q -f status=exited)
    
    if [ -z "$stopped_containers" ]; then
        echo "  没有已停止的容器"
    else
        echo "  找到已停止的容器: $(echo $stopped_containers | wc -w) 个"
        read -p "  是否删除这些已停止的容器? (y/N): " confirm
        if [[ $confirm == [yY] || $confirm == [yY][eE][sS] ]]; then
            docker rm $stopped_containers
            echo -e "${GREEN}已停止的容器已删除${NC}"
        else
            echo "  跳过删除已停止的容器"
        fi
    fi
    echo ""
}

# 函数:清理未使用的数据
cleanup_unused_data() {
    echo -e "${YELLOW}开始清理未使用的 Docker 数据...${NC}"
    read -p "  是否执行 docker system prune? 这将删除未使用的容器、网络、镜像和构建缓存 (y/N): " confirm
    if [[ $confirm == [yY] || $confirm == [yY][eE][sS] ]]; then
        docker system prune -f
        echo -e "${GREEN}未使用的数据已清理${NC}"
    else
        echo "  跳过清理未使用的数据"
    fi
    echo ""
}

# 函数:清理特定容器的日志(针对大文件)
cleanup_large_logs() {
    echo -e "${YELLOW}查找并清理大日志文件 (>100M)...${NC}"
    
    find /var/lib/docker/containers/ -name "*-json.log" -type f -size +100M | while read logfile; do
        container_id=$(basename $(dirname $logfile))
        log_size=$(du -sh "$logfile" | cut -f1)
        echo "  发现大日志文件: $container_id ($log_size)"
        
        read -p "  是否清空此日志文件? (y/N): " confirm
        if [[ $confirm == [yY] || $confirm == [yY][eE][sS] ]]; then
            > "$logfile"
            echo -e "  ${GREEN}已清空: $container_id${NC}"
        fi
    done
    
    echo ""
}

# 函数:配置日志轮转(daemon.json)
configure_log_rotation() {
    echo -e "${YELLOW}配置 Docker 日志轮转...${NC}"
    
    DOCKER_DAEMON_JSON="/etc/docker/daemon.json"
    
    # 备份现有配置
    if [ -f "$DOCKER_DAEMON_JSON" ]; then
        cp "$DOCKER_DAEMON_JSON" "${DOCKER_DAEMON_JSON}.bak.$(date +%Y%m%d_%H%M%S)"
        echo "  已备份现有配置到 ${DOCKER_DAEMON_JSON}.bak.*"
    fi
    
    # 创建或更新 daemon.json
    cat > "$DOCKER_DAEMON_JSON" <<EOF
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}
EOF
    
    echo -e "${GREEN}日志轮转配置已更新:${NC}"
    echo "  - 单个日志文件最大: 10MB"
    echo "  - 保留日志文件数: 3"
    echo "  需要重启 Docker 服务使配置生效: systemctl restart docker"
    echo ""
}

# 主菜单
show_menu() {
    echo "请选择操作:"
    echo "1) 显示占用空间最大的容器"
    echo "2) 清理所有容器日志文件(清空内容)"
    echo "3) 清理大日志文件 (>100M)"
    echo "4) 清理已停止的容器"
    echo "5) 清理未使用的 Docker 数据"
    echo "6) 配置日志轮转(防止未来日志过大)"
    echo "7) 执行完整清理(选项 2 + 4 + 5)"
    echo "8) 退出"
    echo ""
}

# 主循环
while true; do
    show_menu
    read -p "请输入选项 [1-8]: " choice
    
    case $choice in
        1)
            show_top_containers
            ;;
        2)
            cleanup_logs
            ;;
        3)
            cleanup_large_logs
            ;;
        4)
            cleanup_stopped_containers
            ;;
        5)
            cleanup_unused_data
            ;;
        6)
            configure_log_rotation
            ;;
        7)
            cleanup_logs
            cleanup_stopped_containers
            cleanup_unused_data
            echo -e "${GREEN}完整清理完成!${NC}"
            echo ""
            show_top_containers
            ;;
        8)
            echo "退出"
            exit 0
            ;;
        *)
            echo -e "${RED}无效选项,请重新选择${NC}"
            echo ""
            ;;
    esac
done


# 1. 下载脚本并赋予执行权限
chmod +x cleanup_docker_containers.sh

# 2. 以 root 权限运行
sudo ./cleanup_docker_containers.sh

运行结果
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  1. 快速清理脚本
    quick_cleanup.sh - 快速一键清理脚本
    自动执行:清空日志 → 删除已停止容器 → 清理未使用数据
    适合紧急情况快速释放空间
#!/bin/bash

# 快速清理脚本 - 一键降低 Docker 容器磁盘使用

set -e

echo "=========================================="
echo "Docker 容器快速清理"
echo "=========================================="
echo ""

# 检查是否为 root 用户
if [ "$EUID" -ne 0 ]; then 
    echo "错误: 请使用 root 权限运行此脚本"
    exit 1
fi

# 显示清理前状态
echo "清理前磁盘使用情况:"
du -sh /var/lib/docker/containers/* 2>/dev/null | sort -hr | head -5
echo ""

# 1. 清空所有容器日志
echo "步骤 1/3: 清空所有容器日志文件..."
find /var/lib/docker/containers/ -name "*-json.log" -type f -exec truncate -s 0 {} \; 2>/dev/null
echo "✓ 日志文件已清空"
echo ""

# 2. 清理已停止的容器
echo "步骤 2/3: 清理已停止的容器..."
stopped_count=$(docker ps -a -q -f status=exited 2>/dev/null | wc -l)
if [ "$stopped_count" -gt 0 ]; then
    docker rm $(docker ps -a -q -f status=exited) 2>/dev/null || true
    echo "✓ 已删除 $stopped_count 个已停止的容器"
else
    echo "✓ 没有已停止的容器"
fi
echo ""

# 3. 清理未使用的数据(不删除镜像)
echo "步骤 3/3: 清理未使用的 Docker 数据..."
docker system prune -f 2>/dev/null || true
echo "✓ 未使用的数据已清理"
echo ""

# 显示清理后状态
echo "清理后磁盘使用情况:"
du -sh /var/lib/docker/containers/* 2>/dev/null | sort -hr | head -5
echo ""

echo "=========================================="
echo "清理完成!"
echo "=========================================="


方法 2: 手动清理命令

2.1 清理所有容器日志(最常用,立即见效)
# 查找并清空所有日志文件
find /var/lib/docker/containers/ -name "*-json.log" -exec truncate -s 0 {} \;

# 或者使用更安全的方式(保留文件但清空内容)
find /var/lib/docker/containers/ -name "*-json.log" -type f | while read logfile; do
    > "$logfile"
done
2.2 清理特定大容器的日志
# 针对占用 181G 的容器
> /var/lib/docker/containers/5ae1c9345a6e6da0ece25698f6214a90b874417ba61b2e61f2af0413a844bb02/5ae1c9345a6e6da0ece25698f6214a90b874417ba61b2e61f2af0413a844bb02-json.log

# 针对占用 15G 的容器
> /var/lib/docker/containers/e433a85edaaea86855c6518397c388f88493714ee073f370d270e4e3b118f7f0/e433a85edaaea86855c6518397c388f88493714ee073f370d270e4e3b118f7f0-json.log
2.3 清理已停止的容器
# 查看已停止的容器
docker ps -a -f status=exited

# 删除所有已停止的容器
docker rm $(docker ps -a -q -f status=exited)
2.4 清理未使用的 Docker 数据
# 清理未使用的容器、网络、镜像和构建缓存
docker system prune -a -f

# 仅清理未使用的容器和网络(保留镜像)
docker system prune -f

预防措施:配置日志轮转

为了防止未来日志文件再次过大,需要配置 Docker 日志轮转:

1. 编辑 Docker daemon 配置

# 编辑或创建配置文件
vi /etc/docker/daemon.json

2. 添加以下内容

{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}

配置说明:

  • max-size: 单个日志文件最大 10MB
  • max-file: 保留 3 个日志文件(总共最多 30MB)

3. 重启 Docker 服务

systemctl restart docker

4. 验证配置

docker info | grep -i logging

针对运行中容器的日志清理

如果容器正在运行,不能直接删除日志文件,但可以:

方法 A: 临时清空日志(容器继续运行)

# 找到容器的日志文件
CONTAINER_ID="5ae1c9345a6e6da0ece25698f6214a90b874417ba61b2e61f2af0413a844bb02"
LOG_FILE="/var/lib/docker/containers/${CONTAINER_ID}/${CONTAINER_ID}-json.log"

# 清空日志(保留文件)
> "$LOG_FILE"

方法 B: 重启容器并配置日志限制

# 停止容器
docker stop <container_name_or_id>

# 启动时指定日志选项
docker run --log-opt max-size=10m --log-opt max-file=3 <other_options> <image>

检查清理效果

# 查看清理后的磁盘使用情况
du -sh /var/lib/docker/containers/* | sort -hr

# 查看整体 Docker 数据使用情况
docker system df

注意事项

  1. 备份重要日志: 清理前如果日志中有重要信息,先备份

    cp /var/lib/docker/containers/<container_id>/*-json.log /backup/
    
  2. 容器状态: 清理日志不会影响正在运行的容器,但会丢失历史日志

  3. 定期清理: 建议设置定时任务定期清理

    # 添加到 crontab(每周日凌晨 2 点清理)
    0 2 * * 0 find /var/lib/docker/containers/ -name "*-json.log" -size +100M -exec truncate -s 0 {} \;
    
  4. 监控磁盘: 设置磁盘使用率告警,及时发现问题

紧急情况快速处理

如果磁盘空间严重不足,立即执行:

# 1. 清空所有容器日志(最快)
find /var/lib/docker/containers/ -name "*-json.log" -exec truncate -s 0 {} \;

# 2. 清理未使用的 Docker 数据
docker system prune -a -f

# 3. 检查效果
df -h /var/lib/docker

常见问题

Q: 清理日志会影响正在运行的容器吗?
A: 不会。清空日志文件只是删除文件内容,不会影响容器运行。truncate -s 0 只清空内容,不删除文件

Q: 如何找到占用空间最大的容器?
A: 使用 du -sh /var/lib/docker/containers/* | sort -hr | head -10

Q: 日志轮转配置后需要重启容器吗?
A: 需要重启 Docker 服务,但现有容器需要重新创建才能应用新配置。

Q: 可以删除整个容器目录吗?
A: 不建议。应该使用 docker rm 命令删除容器,让 Docker 自动清理相关文件。

更多推荐