Docker 清理指南:高效管理镜像、容器与数据卷

本指南详细介绍了如何使用 Docker 命令清理和管理您的系统,包括删除 Docker 镜像、容器、数据卷和网络,以释放磁盘空间并保持 Docker 环境整洁。内容涵盖一键清理、特定资源删除、常见错误排查及最佳实践。

阅读时长: 10 分钟
共 4850字
作者: eimoon.com

引言

在使用 Docker 进行开发和部署时,随着时间的推移,系统中会积累大量的未使用或“悬挂”(dangling)的镜像(Images)、容器(Containers)、数据卷(Volumes)和网络(Networks)。这些残留资源不仅会占用宝贵的磁盘空间,还可能导致混淆或潜在的冲突。本指南将详细介绍如何利用 Docker 提供的命令来高效清理和管理您的 Docker 环境,确保系统保持整洁和最佳运行状态。

一键清理 Docker 资源:docker system prune

Docker 提供了一个强大的命令 docker system prune,可以帮助您快速清理系统中“悬挂”的资源。所谓“悬挂”资源,是指那些已经存在但没有被任何标记引用或没有与任何容器关联的资源。

要清理所有未使用的或悬挂的镜像、容器、数据卷和网络,可以使用以下命令:

docker system prune

执行此命令时,系统会提示您确认操作,因为它会删除:

  • 所有已停止的容器
  • 所有未被任何容器使用的网络
  • 所有悬挂的镜像
  • 所有未被容器引用的构建缓存

如果您希望进一步清理,包括删除所有已停止的容器和所有未使用的镜像(不仅仅是悬挂镜像),可以添加 -a--all 标志:

docker system prune -a

此命令会删除所有已停止的容器和所有未被任何容器使用的镜像(包括悬挂镜像和未使用但有标签的镜像),但不会删除数据卷。如果需要清理数据卷,请继续阅读。

删除 Docker 镜像 (Images)

镜像(Image)是构建容器的基础。随着项目迭代或测试,可能会留下许多无用的镜像层或完整镜像。

删除一个或多个特定镜像

首先,使用 docker images -a 列出所有本地存在的镜像,包括中间层镜像。然后,通过镜像 ID 或标签将其传递给 docker rmi 命令进行删除。

列出所有镜像:

docker images -a

删除特定镜像:

docker rmi <ImageID_或_ImageName:Tag> <ImageID_或_ImageName:Tag>

注意:

  • -a--all 标志显示所有 Docker 镜像,包括未被任何标签引用的中间镜像层。
  • -f--force 标志可以用于强制删除正在被容器使用的镜像。但在强制删除前,通常建议先停止并删除相关容器。

删除悬挂的 Docker 镜像

悬挂镜像(Dangling Images)是指那些没有被任何标签引用,但其父层可能仍被其他标记镜像引用的镜像层。它们通常是由于镜像构建失败或新版本镜像覆盖旧版本后留下的。

列出悬挂镜像:

docker images -f dangling=true

删除悬挂镜像:

docker image prune

此命令会自动查找并删除所有悬挂的镜像。

根据模式删除镜像

如果您需要删除符合特定命名模式的镜像,可以结合使用 docker imagesgrepawkxargs 命令。

列出符合模式的镜像:

docker images -a | grep "<pattern>"

例如,查找所有名称中包含 “old_project” 的镜像。

删除符合模式的镜像:

docker images -a | grep "<pattern>" | awk '{print $1":"$2}' | xargs docker rmi

此命令首先列出所有镜像,然后通过 grep 过滤出匹配 <pattern> 的行,接着 awk 提取镜像的名称和标签(如 image_name:tag),最后 xargs 将这些名称和标签作为参数传递给 docker rmi 进行删除。

删除所有镜像

有时,为了彻底清理或从头开始,您可能需要删除本地所有的 Docker 镜像。

列出所有镜像的 ID:

docker images -a -q

删除所有镜像:

docker rmi $(docker images -a -q)

此命令会获取所有镜像的 ID,然后将它们作为参数传递给 docker rmi 命令进行删除。请注意,如果某个镜像正在被运行中的容器使用,则无法删除。您可能需要先停止并删除相关容器,或使用 -f 标志强制删除(不推荐)。

删除 Docker 容器 (Containers)

容器(Container)是 Docker 应用程序的运行实例。停止的容器虽然不再消耗 CPU 和内存,但仍会占用磁盘空间。

删除一个或多个特定容器

首先,使用 docker ps -a 命令列出所有容器,包括运行中和已停止的容器。然后,通过容器的 ID 或名称将其传递给 docker rm 命令进行删除。

列出所有容器:

docker ps -a

删除特定容器:

docker rm <ContainerID_或_ContainerName> <ContainerID_或_ContainerName>

退出时自动删除容器

在创建容器时,可以通过添加 --rm 标志,让 Docker 在容器退出时自动将其删除。这对于一次性任务或测试非常有用。

运行并自动删除:

docker run --rm <image_name>

删除所有已停止的容器

已停止的容器通常是清理的首要目标,因为它们不会再被使用。

列出所有已停止的容器:

docker ps -a -f status=exited

删除所有已停止的容器:

docker rm $(docker ps -a -f status=exited -q)

docker ps -a -f status=exited -q 会列出所有状态为 exited 的容器 ID,然后 docker rm 会批量删除它们。

使用多个过滤器删除容器

docker ps 命令支持通过重复 -f 标志来组合多个过滤器。例如,您可以删除状态为 createdexited 的容器。

列出符合多个过滤条件的容器:

docker ps -a -f status=exited -f status=created

删除符合多个过滤条件的容器:

docker rm $(docker ps -a -f status=exited -f status=created -q)

根据模式删除容器

与删除镜像类似,您也可以根据容器名称或镜像名称模式来删除容器。

列出符合模式的容器:

docker ps -a | grep "<pattern>"

删除符合模式的容器:

docker ps -a | grep "<pattern>" | awk '{print $1}' | xargs docker rm

停止并删除所有容器

如果需要彻底清理,可以停止并删除所有正在运行和已停止的容器。

列出所有容器:

docker ps -a

停止并删除所有容器:

docker stop $(docker ps -a -q)
docker rm $(docker ps -a -q)

警告: 这会停止并删除您所有的 Docker 容器,请谨慎操作。

删除 Docker 数据卷 (Volumes)

数据卷(Volume)是 Docker 持久化数据的方式,它们独立于容器的生命周期。即使容器被删除,其关联的数据卷可能仍然存在,占用磁盘空间。

删除一个或多个特定数据卷

首先,使用 docker volume ls 命令列出所有数据卷。然后,通过数据卷名称将其传递给 docker volume rm 命令进行删除。

列出所有数据卷:

docker volume ls

删除特定数据卷:

docker volume rm <volume_name> <volume_name>

删除悬挂数据卷

悬挂数据卷(Dangling Volumes)是指那些存在但未连接到任何容器的数据卷。

列出悬挂数据卷:

docker volume ls -f dangling=true

删除悬挂数据卷:

docker volume prune

此命令会自动查找并删除所有悬挂的数据卷。

删除容器及其数据卷

如果容器使用了未命名(匿名)数据卷,可以在删除容器时,使用 -v 标志一并删除这些数据卷。

删除容器并删除其匿名数据卷:

docker rm -v <container_name_or_id>

注意: 此命令仅删除未命名的数据卷。命名数据卷(Named Volumes)不会被删除,需要手动使用 docker volume rmdocker volume prune 清理。

docker rm, docker rmidocker prune 的区别

理解这些命令的区别对于有效管理 Docker 资源至关重要:

命令 描述 目标 常用标志
docker rm 删除一个或多个 Docker 容器。 容器(Containers) -f 强制删除, -v 删除匿名数据卷
docker rmi 删除一个或多个 Docker 镜像。 镜像(Images) -f 强制删除
docker prune 删除未使用或悬挂的 Docker 资源。 镜像、容器、数据卷、网络 -a 删除所有未使用资源, -f 强制删除

常见错误与调试

在使用 Docker 过程中,可能会遇到一些与清理相关的常见问题。

处理多个容器共享数据卷时的线程同步问题

当多个容器尝试同时写入同一个数据卷时,可能会发生线程同步问题,导致数据损坏或不可预测的行为。

  • 使用命名数据卷 (Named Volumes): 命名数据卷提供了更好的数据共享控制和管理能力。在 Docker Compose 中定义命名数据卷可以清晰地声明其用途。
    version: '3.8'
    services:
      app:
        image: myapp
        volumes:
          - myvolume:/app/node_modules # 多个服务可以引用同一个命名数据卷
      another_app:
        image: another_app_image
        volumes:
          - myvolume:/data/shared
    volumes:
      myvolume: # 定义命名数据卷
    
  • 实现文件锁 (File Locking): 在应用程序层面,使用 flocklockfile 或编程语言提供的互斥锁(Mutex)机制,确保每次只有一个容器访问共享文件。
  • 使用 Docker Compose 编排: Docker Compose 能够定义和管理多容器应用程序,通过 depends_on 等机制可以控制服务启动顺序,但并不能直接解决数据卷写入的并发问题,仍需结合文件锁或设计数据访问模式。
    version: '3.8'
    services:
      app:
        image: myapp
        volumes:
          - myvolume:/app/data
        depends_on: # 确保 db 服务启动后 app 再启动,但这不解决并发写入问题
          - db
      db:
        image: mydb
        volumes:
          - myvolume:/var/lib/mysql
    volumes:
      myvolume:
    
    对于共享数据卷,核心在于应用程序层面的并发控制。

调试因过多镜像层导致的性能瓶颈

Docker 镜像由多个层(Layers)组成,过多的层可能导致镜像臃肿、构建速度慢、部署效率低。

  • 分析镜像层: 使用 docker history <image> 命令检查镜像的构建历史和每一层的大小,识别不必要的层。
    docker history myapp
    
  • 优化 Dockerfile: 将多个 RUN 指令合并为一个,减少生成的层数。例如,将多个 apt install 合并。
    # 不推荐:多条 RUN 指令会产生多层
    # RUN apt update
    # RUN apt install -y python3
    # RUN apt install -y python3-pip
    
    # 推荐:合并 RUN 指令以减少层数
    RUN apt update && apt install -y python3 python3-pip
    
  • 使用多阶段构建 (Multi-stage Builds): 这是 Dockerfile 优化的最佳实践。在不同的构建阶段使用不同的基础镜像和指令,最终只将最终产品(可执行文件、库等)复制到最终的轻量级运行时镜像中,从而大大减小镜像体积和层数。
    # 第一阶段:构建器 (builder)
    FROM golang:1.20 AS builder
    WORKDIR /app
    COPY go.mod go.sum ./
    RUN go mod download
    COPY . .
    RUN CGO_ENABLED=0 GOOS=linux go build -o myapp .
    
    # 第二阶段:最终运行时镜像
    FROM alpine:latest
    WORKDIR /app
    COPY --from=builder /app/myapp . # 只复制构建好的可执行文件
    CMD ["./myapp"]
    

修复尝试删除活动容器时出现的 container is running 错误

当尝试使用 docker rm 命令删除一个正在运行的容器时,Docker 会报错提示 container is running

  1. 先停止容器,再删除: 这是最推荐且最安全的做法。
    docker stop <container_id_或_name>
    docker rm <container_id_或_name>
    
  2. 强制删除容器: 如果确定要强制删除一个正在运行的容器(例如,它卡住或无法正常停止),可以使用 -f--force 标志。这会强制终止容器并删除它,可能导致数据丢失或不完整。
    docker rm -f <container_id_或_name>
    
  3. 停止并删除所有容器: 当需要清理所有容器时,可以先停止所有容器,再批量删除。
    docker stop $(docker ps -a -q) # 停止所有容器
    docker rm $(docker ps -a -q)   # 删除所有容器
    
  4. 使用 Docker Compose 停止并删除: 如果您的应用是通过 Docker Compose 部署的,使用 docker-compose down 命令可以停止并移除 Compose 文件中定义的所有服务、网络和匿名数据卷。
    docker-compose down
    
  5. 通过 Docker Desktop GUI 操作: 如果您使用的是 Docker Desktop,可以直接通过图形用户界面(GUI)停止或删除容器。

常见问题 (FAQs)

  1. 如何删除 Docker 中所有已停止的容器?

    • 对于 Docker Compose 项目:docker-compose down
    • 对于所有已停止的容器和未使用镜像:docker system prune -a
  2. 运行 docker system prune 会发生什么? 它会删除所有已停止的容器、所有未被任何容器使用的网络、所有悬挂的镜像。如果添加 -a 标志,还会删除所有未使用的镜像(包括悬挂镜像和无用的带标签镜像)。

  3. 可以删除正在运行的 Docker 容器吗? 可以,但需要先停止或使用 -f 标志强制删除:docker rm -f <container_id>

  4. 如何释放 Docker 占用的磁盘空间?

    • docker system prune -a:删除所有已停止容器和所有未使用镜像。
    • docker system prune --all --volumes:删除所有已停止容器、所有未使用镜像、所有未使用的网络和所有数据卷。此命令会清除与 Docker 相关的大部分数据,请谨慎使用。
    • docker volume prune:删除所有悬挂数据卷。
    • docker network prune:删除所有未使用的网络。
  5. docker rmdocker rmi 的区别是什么? docker rm 用于删除容器实例,不删除其基于的镜像。docker rmi 用于删除 Docker 镜像,前提是没有容器正在使用该镜像。

  6. 如何彻底删除 Docker 镜像? 使用 docker rmi <image-id>。如果该镜像正在被容器使用,需先停止并删除相关容器,或使用 -f 强制删除(不推荐)。

  7. 如何删除未使用的 Docker 镜像?

    • docker image prune:删除悬挂镜像。
    • docker image prune --all:删除所有未使用(包括悬挂和有标签但未使用的)镜像。
  8. 如何清除所有 Docker 镜像和缓存? 使用 docker system prune --all --volumes警告:此命令将删除与 Docker 相关的所有内容,包括镜像、容器、数据卷和网络。

  9. 如何从 Docker 镜像中删除文件? 不能直接修改现有镜像。您需要在一个基于该镜像的容器中进行修改(删除文件),然后将修改后的容器提交(commit)为一个新的镜像。

    docker run -it <image-id> /bin/bash # 进入容器
    # 在容器内执行删除文件操作,例如:rm /path/to/file
    exit
    docker commit <container-id> <new-image-name> # 提交为新镜像
    
  10. 如何删除所有已停止的 Docker 容器? docker container prunedocker rm $(docker ps -a -f status=exited -q)docker container prune -f 可以跳过确认提示。

  11. 如何删除旧的 Docker 容器? 可以删除处于 exited(已退出)或 created(已创建但未运行)状态的容器:

    docker ps -a --filter "status=exited" --filter "status=created" # 查看
    docker rm $(docker ps -a -q --filter "status=exited" --filter "status=created") # 删除
    
  12. Docker 镜像存储在哪里?

    • Linux: 通常在 /var/lib/docker 目录下。
    • MacOS: 在 Docker Desktop 运行的虚拟机(VM)中。
    • Windows: 在 Docker Desktop 运行的 WSL2 VM 中,或者早期版本在 C:\ProgramData\DockerDesktop。 您可以使用 docker info | grep "Docker Root Dir" 命令来验证实际的存储路径。
  13. Docker 容器完成后如何删除? 在启动容器时使用 --rm 标志,使其在退出时自动删除:

    docker run --rm <image-id>
    

结论

掌握 Docker 资源的清理和管理对于维护一个高效、整洁的开发和生产环境至关重要。本文详细介绍了如何使用 docker system prunedocker rmidocker rmdocker volume rm 等命令来删除不需要的镜像、容器和数据卷。通过定期清理,您可以有效释放磁盘空间,避免潜在的冲突,并优化 Docker 的性能。建议定期执行清理操作,并查阅 Docker 官方文档以获取最新的命令用法和最佳实践。

关于

关注我获取更多资讯

公众号
📢 公众号
个人号
💬 个人号
使用 Hugo 构建
主题 StackJimmy 设计