From 8d284d7ce000b285dc8a4ba4b3f36d267d980f73 Mon Sep 17 00:00:00 2001 From: Michael Wu Date: Tue, 9 Feb 2016 16:21:04 -0500 Subject: [PATCH] Add options to remove all exited containers Use the `-e` flag to remove all exited containers. If used in conjunction with `-c`, it will find all containers that exited or match the `PATTERN` provided. --- README.md | 4 ++++ dockerclean | 26 ++++++++++++++++++-------- tests/docker-compose.yml | 5 +++++ tests/dockerclean-test.bats | 11 +++++++++++ 4 files changed, 38 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index ef26501..06780e7 100644 --- a/README.md +++ b/README.md @@ -6,12 +6,16 @@ A simple utility to make it easier to cleanup Docker images and containers. - `-c PATTERN`: Remove all containers matched by `PATTERN` - `-d`: Remove all images tagged as `` +- `-e`: Remove all exited containers - `-r`: By default `dockerclean` executes in `dry-run` mode to give you a chance to preview any images or containers that will get deleted. Use the `-r` flag to remove matched images and containers. - `-i PATTERN`: Remove all images matched by `PATTERN` - `-h`: Print usage and options +If `-e` and `-c` are used in conjunction, `dockerclean` will find all containers +that have exited or match the `PATTERN` provided. + ## Build status ![master](https://circleci.com/gh/michael-yx-wu/dockerclean/tree/master.png?style=shield&circle-token=810386c47ffeb705bf8c4e52a88c0d2177e82230) (master) diff --git a/dockerclean b/dockerclean index b305745..c3e0b0a 100755 --- a/dockerclean +++ b/dockerclean @@ -10,6 +10,7 @@ grepContainer=false grepContainerPattern='' grepImage=false grepImagePattern='' +exitedContainers=false function displayUsageAndSummary { printf "%s\n\n%s\n" "$usage" "$summary" @@ -19,7 +20,7 @@ function displayHelp { displayUsageAndSummary echo '' declare -A optionsTable - local numFlags=5 + local numFlags=6 optionsTable["0,0"]='-c PATTERN' optionsTable["0,1"]='Remove all containers matched by PATTERN' optionsTable["1,0"]='-d' @@ -28,6 +29,8 @@ function displayHelp { optionsTable["2,1"]='If the -r option is not given, display all images or containers that would be removed' optionsTable["3,0"]='-i PATTERN' optionsTable["3,1"]='Remove all images matched by PATTERN' + optionsTable["5,0"]='-e' + optionsTable["5,1"]='Remove all exited containers' optionsTable["4,0"]='-h' optionsTable["4,1"]='Print usage and options' i=0 @@ -83,15 +86,19 @@ function removeImages { } function gatherContainersToRemove { - if ! "$grepContainer"; then + if "$grepContainer" && "$exitedContainers"; then + docker ps -a | grep -E "$grepContainerPattern|Exited" + elif "$grepContainer"; then + docker ps -a | grep -E "$grepContainerPattern" + elif "$exitedContainers"; then + docker ps -a | grep -E "Exited" + else echo '' - return 0 fi - docker ps -a | grep "$grepContainerPattern" } function removeContainers { - if ! "$grepContainer"; then + if ! "$grepContainer" && ! "$exitedContainers"; then echo '' return 0 fi @@ -99,10 +106,10 @@ function removeContainers { echo 'No matching containers to remove' return 0 fi - docker rm -f $(docker ps -a | grep $grepContainerPattern | awk '{print $NF}') + docker rm -f $(echo "$1" | awk '{print $1}') } -while getopts ":c:dri:h" option; do +while getopts ":c:deri:h" option; do case "$option" in h) displayHelp @@ -118,6 +125,9 @@ while getopts ":c:dri:h" option; do grepContainer=true grepContainerPattern="$OPTARG" ;; + e) + exitedContainers=true + ;; i) grepImage=true grepImagePattern="$OPTARG" @@ -137,7 +147,7 @@ while getopts ":c:dri:h" option; do esac done -if ! { "$dangling" || "$grepContainer" || "$grepImage"; } then +if ! { "$dangling" || "$grepContainer" || "$grepImage" || "$exitedContainers"; } then echo 'Nothing will be removed: no removal strategy specified' echo '' displayHelpPrompt diff --git a/tests/docker-compose.yml b/tests/docker-compose.yml index 398a606..22f1860 100644 --- a/tests/docker-compose.yml +++ b/tests/docker-compose.yml @@ -12,3 +12,8 @@ cirros030: container_name: cirros.030.dockerclean image: cirros:0.3.0 command: sleep 300 + +cirrosexited: + container_name: cirros.exited.dockerclean + image: cirros:0.3.0 + command: sleep 0 diff --git a/tests/dockerclean-test.bats b/tests/dockerclean-test.bats index dbe0ed1..219368b 100755 --- a/tests/dockerclean-test.bats +++ b/tests/dockerclean-test.bats @@ -54,6 +54,7 @@ setup() { export alpine_26_container_id=$(docker inspect --format={{.Id}} alpine.26.dockerclean) export alpine_latest_container_id=$(docker inspect --format={{.Id}} alpine.32.dockerclean) export cirros_latest_container_id=$(docker inspect --format={{.Id}} cirros.030.dockerclean) + export cirros_exited_container_id=$(docker inspect --format={{.Id}} cirros.exited.dockerclean) } @test "matches containers without removing" { @@ -69,6 +70,16 @@ setup() { nothingRemoved } +@test "matches exited containers without removing" { + results=$(./dockerclean -e) + num_results=$(echo "$results" | grep cirros | grep Exited | wc -l) + [ "$num_results" -eq 1 ] + cirros_exited_matched_container_id=$(docker inspect --format={{.Id}} $(echo "$results" | grep cirros | grep Exited | awk '{print $1}')) + [ "$alpine_exited_matched_container_id" = "$alpine_exited_container_id" ] + + nothingRemoved +} + @test "matches images without removing" { results=$(./dockerclean -i alpine) num_results=$(echo "$results" | grep alpine | wc -l)