Skip to content

Commit

Permalink
Merge pull request #8 from michael-yx-wu/develop
Browse files Browse the repository at this point in the history
  • Loading branch information
Michael Wu committed Feb 9, 2016
2 parents e08d495 + 8d284d7 commit ed86c09
Show file tree
Hide file tree
Showing 5 changed files with 178 additions and 15 deletions.
17 changes: 12 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
dockerclean
===========
# dockerclean
A simple utility to make it easier to cleanup Docker images and containers.

Usage
-----
## Usage
`dockerclean [OPTIONS]`

- `-c PATTERN`: Remove all containers matched by `PATTERN`
- `-d`: Remove all images tagged as `<none>`
- `-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.
- `-t PATTERN`: Remove all images matched by `PATTERN`
- `-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)

![develop](https://circleci.com/gh/michael-yx-wu/dockerclean/tree/develop.png?style=shield&circle-token=810386c47ffeb705bf8c4e52a88c0d2177e82230) (develop)
15 changes: 15 additions & 0 deletions circle.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
machine:
pre:
- sudo curl -L -o /usr/bin/docker 'https://s3-external-1.amazonaws.com/circle-downloads/docker-1.9.1-circleci'
- sudo chmod 0755 /usr/bin/docker
services:
- docker

dependencies:
pre:
- git clone https://github.com/sstephenson/bats.git; cd bats; sudo ./install.sh /usr/local
- docker -v

test:
override:
- bats tests
30 changes: 20 additions & 10 deletions dockerclean
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ grepContainer=false
grepContainerPattern=''
grepImage=false
grepImagePattern=''
exitedContainers=false

function displayUsageAndSummary {
printf "%s\n\n%s\n" "$usage" "$summary"
Expand All @@ -19,15 +20,17 @@ 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'
optionsTable["1,1"]='Remove all images tagged as <none>'
optionsTable["2,0"]='-r'
optionsTable["2,1"]='If the -r option is not given, display all images or containers that would be removed'
optionsTable["3,0"]='-t PATTERN'
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
Expand Down Expand Up @@ -83,26 +86,30 @@ 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
if [ -z "$1" ]; then
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:drt:h" option; do
while getopts ":c:deri:h" option; do
case "$option" in
h)
displayHelp
Expand All @@ -118,7 +125,10 @@ while getopts ":c:drt:h" option; do
grepContainer=true
grepContainerPattern="$OPTARG"
;;
t)
e)
exitedContainers=true
;;
i)
grepImage=true
grepImagePattern="$OPTARG"
;;
Expand All @@ -137,7 +147,7 @@ while getopts ":c:drt: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
Expand Down
19 changes: 19 additions & 0 deletions tests/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
alpine26:
container_name: alpine.26.dockerclean
image: alpine:2.6
command: sleep 300

alpine32:
container_name: alpine.32.dockerclean
image: alpine:3.2
command: sleep 300

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
112 changes: 112 additions & 0 deletions tests/dockerclean-test.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
#!/usr/bin/env bats

nothingRemoved() {
run docker inspect alpine:2.6
[ "$status" -eq 0 ]
run docker inspect alpine:3.2
[ "$status" -eq 0 ]
run docker inspect cirros:0.3.0
[ "$status" -eq 0 ]
run docker inspect alpine.26.dockerclean
[ "$status" -eq 0 ]
run docker inspect alpine.32.dockerclean
[ "$status" -eq 0 ]
run docker inspect cirros.030.dockerclean
[ "$status" -eq 0 ]
}

alpineImagesRemoved() {
run docker inspect alpine:2.6
[ "$status" -eq 1 ]
run docker inspect alpine:3.2
[ "$status" -eq 1 ]
run docker inspect cirros:0.3.0
[ "$status" -eq 0 ]
run docker inspect alpine.26.dockerclean
[ "$status" -eq 1 ]
run docker inspect alpine.32.dockerclean
[ "$status" -eq 1 ]
run docker inspect cirros.030.dockerclean
[ "$status" -eq 0 ]
}

alpineContainersRemoved() {
run docker inspect alpine:2.6
[ "$status" -eq 0 ]
run docker inspect alpine:3.2
[ "$status" -eq 0 ]
run docker inspect cirros:0.3.0
[ "$status" -eq 0 ]
run docker inspect alpine.26.dockerclean
[ "$status" -eq 1 ]
run docker inspect alpine.32.dockerclean
[ "$status" -eq 1 ]
run docker inspect cirros.030.dockerclean
[ "$status" -eq 0 ]
}

setup() {
docker-compose -f tests/docker-compose.yml -p dockerclean-tests up -d
sleep 5
export alpine_26_image_id=$(docker inspect --format={{.Id}} alpine:2.6)
export alpine_latest_image_id=$(docker inspect --format={{.Id}} alpine:3.2)
export cirros_latest_image_id=$(docker inspect --format={{.Id}} cirros:0.3.0)
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" {
results=$(./dockerclean -c alpine)
num_results=$(echo "$results" | grep alpine | wc -l)
[ "$num_results" -eq 2 ]

alpine_26_matched_container_id=$(docker inspect --format={{.Id}} $(echo "$results" | grep alpine | grep "2\.6" | awk '{print $1}'))
alpine_latest_matched_container_id=$(docker inspect --format={{.Id}} $(echo "$results" | grep alpine | grep "3\.2" | awk '{print $1}'))
[ "$alpine_26_matched_container_id" = "$alpine_26_container_id" ]
[ "$alpine_latest_matched_container_id" = "$alpine_latest_container_id" ]

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)
[ "$num_results" -eq 2 ]

alpine_26_matched_image_id=$(docker inspect --format={{.Id}} $(echo "$results" | grep alpine | grep "2\.6" | awk '{print $3}'))
alpine_latest_matched_image_id=$(docker inspect --format={{.Id}} $(echo "$results" | grep alpine | grep "3\.2" | awk '{print $3}'))
[ "$alpine_26_matched_image_id" = "$alpine_26_image_id" ]
[ "$alpine_latest_matched_image_id" = "$alpine_latest_image_id" ]

nothingRemoved
}

@test "removes containers" {
skip "CircleCI does not allow deletion of containers"

results=$(./dockerclean -r -c alpine)
alpineContainersRemoved
}

@test "removes images (after removing containers)" {
skip "CircleCI does not allow deletion of containers"

run ./dockerclean -r -c alpine
[ "$status" -eq 0 ]

results=$(./dockerclean -r -i alpine)
sleep 1
alpineImagesRemoved
}

0 comments on commit ed86c09

Please sign in to comment.