1. 引言
我们之前已经了解了 Docker 镜像和容器的区别。简单来说,镜像就像 Java 中的类,而容器则像是类的实例对象。
在本文中,我们将聚焦于 Docker 镜像的各种删除方式,帮助我们释放磁盘空间并保持 Docker 引擎的整洁。
2. 为什么需要删除 Docker 镜像?
Docker 引擎负责存储镜像、运行容器,以及管理全局卷、网络等资源。为此,Docker 引擎会预留一部分磁盘空间作为“存储池”。
一旦这个存储池满了,Docker 就会停止工作。我们无法再创建或下载新的镜像,容器也会无法运行。
镜像是 Docker 存储池中占用空间最多的部分,因此我们需要删除不需要的镜像来释放空间。
此外,删除镜像也有助于保持 Docker 引擎的整洁。例如,在开发过程中我们可能会创建大量临时镜像,或者下载了一些用于测试的镜像,这些都可以在使用后删除。
对于从远程仓库拉取的镜像,删除后我们可以随时再次拉取。但如果是自己构建的镜像,就需要注意备份。一旦删除且未保存或上传,镜像将永久丢失。可以通过推送到仓库或 导出为 TAR 文件 来进行备份。
3. 下载 PostgreSQL 13 Beta 镜像
PostgreSQL 是一个开源的关系型数据库。我们以两个 PostgreSQL 13 beta 的 Docker 镜像为例进行演示。这两个镜像体积较小,下载速度快。由于是 beta 版本,我们本地 Docker 引擎中应该还没有它们。
在下载之前,先查看当前 Docker 引擎中镜像的占用情况:
$ docker system df --format 'table {{.Type}}\t{{.TotalCount}}\t{{.Size}}'
输出示例(仅显示第一行):
TYPE TOTAL SIZE
Images 71 7.813GB
接下来,下载两个 PostgreSQL 镜像并再次查看:
$ docker pull postgres:13-beta1-alpine
$ docker pull postgres:13-beta2-alpine
$ docker system df --format 'table {{.Type}}\t{{.TotalCount}}\t{{.Size}}'
输出示例:
TYPE TOTAL SIZE
Images 73 8.119GB
可以看到,镜像数量增加了 2 个,总大小增加了约 300MB。
4. 删除单个镜像
我们先用 PostgreSQL 13 beta 2 镜像启动一个容器:
$ docker run -d -e POSTGRES_PASSWORD=secr3t postgres:13-beta2-alpine
$ docker ps --format 'table {{.ID}}\t{{.Image}}\t{{.Status}}'
输出示例:
CONTAINER ID IMAGE STATUS
527bfd4cfb89 postgres:13-beta2-alpine Up Less than a second
尝试删除该镜像:
$ docker image rm postgres:13-beta2-alpine
此时会报错,因为该镜像正在被一个容器使用:
Error response from daemon: conflict: unable to remove repository reference
"postgres:13-beta2-alpine" (must force) - container 527bfd4cfb89 is using its referenced image cac2ee40fa5a
我们需要先停止并删除容器:
$ docker container stop 527bfd4cfb89
$ docker container rm 527bfd4cfb89
然后再删除镜像:
$ docker image rm postgres:13-beta2-alpine
输出示例:
Untagged: postgres:13-beta2-alpine
Untagged: postgres@sha256:b3a4ebdb37b892696a7bd7e05763b938345f29a7327fc17049c7148c03ff6a92
removed: sha256:cac2ee40fa5a40f0abe53e0138033fe7a9bcee28e7fb6c9eaac4d3a2076b1a86
...
最后确认空间已释放:
$ docker system df
输出示例:
TYPE TOTAL SIZE
Images 72 7.966GB
5. 按名称删除多个镜像
再次拉取 beta 2 镜像:
$ docker pull postgres:13-beta2-alpine
现在我们想同时删除 beta1 和 beta2 的镜像。由于 docker image rm
不支持按名称过滤,我们可以借助 Linux 命令组合实现:
$ docker image ls --format '{{.Repository}}:{{.Tag}}' | grep '^postgres:13-beta'
输出示例:
postgres:13-beta2-alpine
postgres:13-beta1-alpine
然后执行删除命令:
$ docker image rm $(docker image ls --format '{{.Repository}}:{{.Tag}}' | grep '^postgres:13-beta')
⚠️ 注意:必须确保没有容器使用这些镜像,否则删除失败。
6. 按大小删除镜像
为了节省空间,可以优先删除体积较大的镜像。使用如下命令按大小排序:
$ docker image ls | sort -k7 -h -r
输出示例:
collabora/code 4.2.5.3 8ae6850294e5 3 weeks ago 1.28GB
nextcloud 19.0.1-apache 25b6e2f7e916 6 days ago 752MB
nextcloud latest 6375cff75f7b 5 weeks ago 750MB
我们可以通过镜像 ID 一次性删除多个镜像:
$ docker image rm 6375cff75f7b 5c44e8445287
确认删除后空间释放:
TYPE TOTAL SIZE
Images 69 7.128GB
7. 按创建时间删除镜像
Docker 也支持按创建时间删除镜像。我们可以使用 docker image prune
命令:
$ docker image prune -a --force --filter "until=2020-07-07T00:00:00"
也可以指定时间跨度(单位为小时):
$ docker image prune -a --force --filter "until=168h"
⚠️ 注意:-a
参数表示删除所有未被使用的镜像,非常危险,使用时需谨慎。
8. 清理容器和镜像
docker image prune
可以批量删除未被使用的镜像,与之配合使用的还有 docker container prune
,用于批量删除已停止的容器。
清理容器
$ docker container prune
确认删除:
WARNING! This will remove all stopped containers.
Are you sure you want to continue? [y/N] y
清理镜像
$ docker image prune
默认只删除“悬空镜像(dangling images)”,即未被任何容器使用的中间镜像。
如果想删除所有未被使用的镜像:
$ docker image prune -a
⚠️ 危险操作:该命令会删除所有未被容器引用的镜像,慎用!
9. 强制删除容器和镜像
9.1 删除所有容器
$ docker rm $(docker ps -qa)
⚠️ 如果有容器正在运行,会报错:
Error response from daemon: cannot remove container "/<CONTAINER_NAME>":
container is running: stop the container before removing or force remove
9.2 强制删除所有容器
$ docker rm -f $(docker ps -qa)
✅ -f
参数会强制终止并删除所有容器,包括正在运行的。
9.3 删除所有镜像
$ docker rmi $(docker images -aq)
⚠️ 如果有容器正在使用某个镜像,删除失败。
9.4 强制删除所有镜像
$ docker rmi -f $(docker images -aq)
✅ -f
参数会强制删除镜像,即使它被容器引用(但不会删除正在运行的容器所使用的镜像)。
⚠️ 删除后可能出现 <none>
标签的“悬空镜像”,可以后续使用 docker image prune
清理。
10. 总结
本文我们学习了以下内容:
✅ 删除单个镜像的方法
✅ 按名称、大小、创建时间批量删除镜像
✅ 使用 docker image prune
和 docker container prune
清理资源
✅ 强制删除所有容器和镜像的方式
⚠️ 注意:删除操作具有破坏性,特别是带有 -f
和 -a
参数的命令,务必确认后再执行。建议在执行前使用 docker system df
检查当前存储情况,避免误删重要镜像或容器。