背景
刚开始制作镜像(docker build)并启动容器(docker run)时,可能不会一次做好,为了防止占用空间,经常涉及到删除已制作的镜像(docker rmi)并重新build,但是此时镜像可能被某个已经Exited的容器加载,导致无法删除(需要先删除container,docker rm),如下所示:
即每次docker rmi之前都要docker ps –a(查看所有容器)、docker rm(删除已经exited的容器),太麻烦,因而就想着如何一步删除所有exited的容器。
源码
#!/bin/ksh
#docker ps -a | sed '/^CONTAINER/d' | grep "Exited" | gawk '{print $1}'
docker ps -a | sed '/^CONTAINER/d' | grep "Exited" | gawk '{cmd="docker rm "$1; system(cmd)}'
解释
- 整个脚本就1行,#!是解释器,第二句gawk '{print $1}'是本人用于调试目的写的(已被注释);
- 首先是docker ps –a查看所有容器(包括已退出的);
- 后面用sed过滤(删除)docker ps –a的显示标题行(^CONTAINER表示以CONTAINER开头):
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES - 在后面进行grep过滤,只选择包含Exited的行;
- 最后用gawk的字段分割功能,用docker rm删除$1指示的容器ID。
测试
如图所示,有三个Exited的容器,通过脚本一次性全部删除,后续就可以用docker rmi删除镜像了。
总结
- 脚本看似简单,但是涉及到sed、grep、gawk以及管道,需要对Linux的命令行有个全面的认识可能才想得到;
- 可能有更好的解决方法,如在docker ps –a后直接用gawk过滤并删除,后续本人将继续改进;
- 正则表达式作为shell脚本的高级应用与终极杀手,就让此脚本就作为本人入门正则表达式的第一章吧。
完。