Tao
Tao

Docker镜像删除与系统清理完整指南

管理Docker镜像对docker运维人员来说是日常管理工作的一部分。随着docker镜像的增多,它们会占用大量磁盘空间,通过一行命令删除镜像对我们来说很简单,但是作为运维人员还需要理解Docker的底层机制。本文将介绍下docker镜像删除相关的命令及最佳实践,同时介绍下docker镜像结构,帮助大家更加理解docker技术。

Docker 镜像并非一个单一的、庞大的文件。它是一个轻量级、独立、可执行的软件包,包含了运行应用程序所需的一切:代码、运行时、系统工具、系统库和设置。 这个包由一系列只读层构成,每一层都代表了镜像 Dockerfile 中的一个特定指令。这种分层架构是Docker高效性的基础,因为层可以在不同镜像之间共享,从而最大限度地减少存储占用并加快构建和拉取速度。

镜像 ID

  • 唯一标识符,是基于镜像配置和层计算的 SHA256 哈希值
  • 例如:eeae25ada2aa

标签 (Tag)

  • 人类可读的标签,指向镜像 ID
  • 格式:仓库名:标签名,如 ubuntu:22.04nginx:latest
  • 一个镜像 ID 可以有多个标签

摘要 (Digest)

  • 镜像清单文件的 SHA256 哈希值
  • 不可变,保证每次引用的是完全相同的镜像版本

这些标识符之间的区别至关重要。标签是一个可变的指针,而镜像 ID 代表实际的对象。当用户尝试删除一个镜像时,他们通常首先与指针(标签)进行交互。例如,如果一个 ID 为 fd484f19954f 的镜像有两个标签 test1:latest 和 test2:latest,运行 docker rmi test1:latest 并不会删除底层的镜像数据。它只会移除 test1:latest 这个标签。命令的输出会通过显示 Untagged: test1:latest 来反映这一点。镜像层和 ID fd484f19954f 仍然保留在系统上,因为它们仍被 test2:latest 标签引用。只有当指向一个镜像 ID 的最后一个标签被移除时,Docker 才会尝试删除镜像层本身,从而在输出中产生一条 Deleted: sha256:… 的消息。 这种管理引用的概念是 Docker 镜像移除最基本的原则

主要命令是 docker image rm,简写为 docker rmi

bash

# 删除单个镜像
docker rmi redis:latest

# 删除多个镜像
docker rmi redis:latest nginx:stable alpine:3.18

bash

# 使用短 ID
docker rmi eeae25ada2aa

bash

docker rmi my-registry/my-repo@sha256:cbbf2f9a99b47fc460d422812b6a5adff7dfee951d8fa2e4a98caa0382cfbdbf

常见错误:Error response from daemon: conflict: unable to remove image...: it is being used by one or more containers

这个错误发生是因为 Docker 会保护正在被容器使用的镜像,包括已停止的容器。

  1. 找出依赖的容器

bash

# 查看所有容器
docker ps -a

# 查找特定镜像的容器
docker ps -a --filter "ancestor=nginx:latest"
  1. 停止运行中的容器

bash

docker stop <container_id_or_name>
  1. 删除容器

bash

docker rm <container_id_or_name>
  1. 重新删除镜像

bash

docker rmi <image_name>

Docker的默认删除流程虽然安全可靠,但在实际使用中,我们有时需要绕过这些保护机制。比如处理多标签镜像或多平台构建时,就需要用到一些高级参数。不过使用这些强制删除功能时,一定要明确了解可能带来的风险。

-f--force 标志可以绕过某些安全检查,但要谨慎使用。

如果一个镜像 ID(例如 fd484f19954f)被多个标签(test1:latest, test:latest, test2:latest)引用,尝试不带强制标志按其 ID 移除将会导致错误,因为Docker不会移除仍有标签指向的镜像。使用docker rmi -f <IMAGE_ID>可以覆盖这一点。它会强制取消所有相关引用的标签,然后删除镜像层。

bash

# 强制删除有多个标签的镜像
# 这个命令将取消 test1:latest, test:latest, 和 test2:latest 的标签,然后删除镜像 fd484f19954f
docker rmi -f fd484f19954f

需要注意一点,docker rmi -f 不能移除一个正在运行中的容器所使用的镜像。然而它可以用来移除一个被已停止的容器所引用的镜像。

当对一个被已停止容器使用的镜像执行 docker rmi -f <image_name> 命令时,表面上看起来操作成功了,镜像也从 docker images 列表中消失了。但实际上,镜像层并没有真正从文件系统中删除。由于已停止的容器依然存在,它对父镜像层的引用关系仍然保留在磁盘上,这就造成了一种"孤立"的容器状态。

用户可能误以为已经释放了磁盘空间,但这些数据实际上仍然占用着存储资源,只有当容器本身通过 docker rm 命令被明确删除后,相关的镜像层才会真正被清理。这种情况可能导致"隐藏"的磁盘占用问题,并且会让系统状态变得难以调试和理解。

建议:最好先删除容器,再删除镜像。

现代应用常需要支持多种CPU架构(如 amd64 和 arm64)。

bash

# 只删除特定平台的镜像
docker image rm --platform=linux/arm64 my-app:latest

“悬空"镜像是没有标签且未被容器引用的镜像层。

bash

# 清理悬空镜像(会提示确认)
docker image prune

# 跳过确认
docker image prune -f

“未使用"镜像是指没有与任何容器关联的镜像。

bash

# 清理所有未使用镜像
docker image prune -a

警告:这会删除所有没有容器关联的镜像,在 CI/CD 环境中可能有破坏性。

docker system prune 是最全面的清理工具。

bash

docker system prune

清理内容:

  • 所有已停止的容器
  • 所有未使用的网络
  • 所有悬空镜像
  • 所有构建缓存

bash

docker system prune -a

额外清理所有未使用的镜像。

bash

docker system prune -a --volumes

极度危险:还会删除所有未使用的卷,可能导致数据丢失。

如需了解更多关于 Docker prune 命令的详细信息,请参考:Docker Prune 完整指南

命令 目标 风险级别 适用场景
docker image rm IMAGE 特定镜像 删除已知不需要的镜像
docker image rm -f IMAGE_ID 强制删除镜像 多标签镜像或被停止容器使用的镜像
docker image prune 悬空镜像 常规清理,最安全
docker image prune -a 所有未使用镜像 开发机器积极清理
docker system prune 所有悬空资源 中低 一般系统清理
docker system prune -a 所有未使用资源 谨慎使用
docker system prune -a --volumes 包括卷 极高 几乎不应使用

对于开发者(本地机器):

  • 防止累积:对临时或测试容器使用 docker run--rm 标志。这会在容器退出时自动移除容器,防止累积持有镜像引用的已停止容器。

  • 常规清理: 定期运行 docker system prune来清除悬空镜像、构建缓存和已停止的容器。这是保持本地环境整洁的低风险方法。也可以在确认没有重要的已停止容器或未使用的镜像需要保留后,使用docker system prune -a

对于 CI/CD 和共享环境:

  • 优先考虑数据安全: 切勿在任何自动化脚本或共享环境中使用 docker system prune –volumes。意外数据丢失的风险太高。

  • 使用标签来执行策略: 为您的镜像实施标签策略。为不同阶段(development, staging, production)或状态(keep, archived)指定标签。然后,清理作业可以使用标签过滤器,如 –filter “label!=stage=production” 或 –filter “label!=keep”,来精确移除资源而不触及关键镜像。

  • 实施保留策略: 在计划的清理作业中使用基于时间的过滤器,如 –filter “until=720h”(30 天),来对镜像和其他资源实施滚动保留策略。这可以防止在长期运行的环境中无限期地消耗资源。

  1. 理解依赖关系:先删除容器,再删除镜像
  2. 选择合适命令工具:从精确的 docker image rm 到广泛的 docker system prune
  3. 环境适配:开发环境可以激进,生产环境要保守
  4. 使用过滤器:实现精确控制而不是盲目删除
  5. 建立策略:通过标签和时间过滤器实现自动化清理

相关内容