TL;DR
# 查找并删除镜像(xxx代表查询条件)
for /f "tokens=3" %i in ('docker images ^| findstr "xxx"') do @docker rmi %i
# 查找并删除容器(xxx代表查询条件)
for /f "tokens=1" %i in ('docker ps -a ^| findstr "xxx"') do @docker rm %i
如果对整个探索过程有兴趣,可以继续往下看。
docker用久了之后,可能会有一些冗余的镜像(和容器),一个一个去删太麻烦了,就会需要批量删除。而且,我想大家对在*NIX环境下的批量删除已经很清楚了:
# 查找并删除镜像(xxx代表查询条件)
docker rmi `docker images | grep xxx | awk '{print $3}'`
# 查找并删除容器(xxx代表查询条件)
docker rm `docker ps -a | grep xxx | awk '{print $1}'`
但是因为我的开发环境是Windows,查了半天也只能查到在*NIX环境下(包括Mac)批量删除docker容器和镜像的方法。难道Windows不仅安装docker麻烦,时不时有点奇怪的bug,甚至连批量删除这点权利都没有吗?
当然,说完全查不到,也是一个夸张的说法;其实我还是看到了两种方法的:
第一种是,把查询结果写入一个txt文件,然后读txt文件的内容进行删除。比如说,假如我要删除所有的容器:
docker ps -a -q > 1.txt
for /f %a in (1.txt) do docker rm %a
但是这个太不优雅了,第一个是要分两步去做,第二个是还会生成一个没啥用的txt文件。
第二种是,手动去装一下Windows版的awk,也就是gawk,然后就可以像在Linux里一样去弄了。当然他并没有说接下来怎么做,这一段是我脑补的:
# 查找并删除镜像(xxx代表查询条件)
for /f %i in ('docker images ^| findstr "xxx" ^| awk "{print $3}"') do @docker rmi %i
# 查找并删除容器(xxx代表查询条件)
for /f %i in ('docker ps -a ^| findstr "xxx" ^| awk "{print $1}"') do @docker rm %i
虽然看上去还不错,但是这个也不是很好。考虑到第一个是要装一个额外的库,并不具有迁移性,不是每个人都会装这个库;第二个是这个库已经很老了,最新版也是08年发布的,虽然现在还能兼容,万一哪一天不兼容了呢?
如果非要杠的话,其实shell命令也有可能发生变化,原生实现也未必稳定;但是总比依赖于第三方的内容要更稳定一些。
好在功夫不负有心人,后来又查了一堆资料,摸索出一个办法。其实也很简单,因为我们需要解决的核心问题其实就是两个,第一个是怎么在Windows下实现类似于awk的那种提取内容的效果,第二个是怎么在Windows下实现类似于Linux中反引号和${}
这种把前一个命令的结果传给后一个命令的效果。这两点原生的for /f
都能做到:
# 查找并删除镜像(xxx代表查询条件)
for /f "tokens=3" %i in ('docker images ^| findstr "xxx"') do @docker rmi %i
# 查找并删除容器(xxx代表查询条件)
for /f "tokens=1" %i in ('docker ps -a ^| findstr "xxx"') do @docker rm %i
整个逻辑相信大家都能看懂,因为有for循环,甚至比Linux那个看起来还要直观一点,但是可能需要稍微解释一下这个tokens,文档是这么说的:
tokens=n The numbered items to read from each line (default = 1)
这个其实就类似于awk '{print $n}'
的效果,这样第一个问题就解决了。而第二个问题,因为是个循环,也就不是问题了。这个命令还有更多的用法,可以参考文档。
所以……没有所以。