Skip to content
This repository has been archived by the owner on Jun 11, 2019. It is now read-only.

Allow wildcards in KEEP_IMAGES and KEEP_CONTAINERS #20

Merged
merged 4 commits into from
Mar 17, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 4 additions & 7 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,11 @@ FROM alpine:latest
# run.sh script uses some bash specific syntax
RUN apk add --update bash docker grep

ENV CLEAN_PERIOD **None** DELAY_TIME **None** KEEP_IMAGES **None** KEEP_CONTAINERS **None** LOOP true DEBUG 0

# Reorder for efficiency
# Install cleanup script
ADD run.sh /run.sh
ADD docker-cleanup-volumes.sh /docker-cleanup-volumes.sh

ENV CLEAN_PERIOD **None**
ENV DELAY_TIME **None**
ENV KEEP_IMAGES **None**
ENV KEEP_CONTAINERS **None**
ENV LOOP true
ADD run.sh /run.sh

ENTRYPOINT ["/run.sh"]
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,29 @@ The default parameters can be overridden by setting environment variables on the
* **KEEP_IMAGES** - List of images to avoid cleaning, e.g. "ubuntu:trusty, ubuntu:latest". Defaults to clean all unused images.
* **KEEP_CONTAINERS** - List of images for exited or dead containers to avoid cleaning, e.g. "ubuntu:trusty, ubuntu:latest".
* **LOOP** - Add the ability to do non-looped cleanups, run it once and exit. Options are true, false. Defaults to true to run it forever in loops.
* **DEBUG** - Set to 1 to enable more debugging output on pattern matches

Note that **KEEP_IMAGES** and **KEEP_CONTAINERS** are left-anchored bash shell pattern matching lists (NOT regexps). Therefore, the image **foo/bar:tag** will be matched by ANY of the following:

* foo/bar:tag
* foo/bar
* foo/b
* [[:alpha:]]/bar
* \*/\*:tag
* \*:tag
* foo/\*:tag

However it will not match

* foo/baz
* bar:tag
* /bar
* :tag
* [[:alpha:]]:tag

By default, both are set to **\*\*None\*\*** which is the same as the blank string. If you want to keep ALL images or containers, effectively disabling this
part of the cleanup, then you should use **\*:\*** to match all images. Do not
use a bare **\*** as this will be taken as a filename match.

## Deployment
The image uses the Docker client to to list and remove containers and images. For this reason the Docker client and socket is mapped into the container.
Expand Down
85 changes: 66 additions & 19 deletions run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -28,37 +28,64 @@ if [ "${KEEP_IMAGES}" == "**None**" ]; then
unset KEEP_IMAGES
fi

arr_keep_containers=""
if [ "${KEEP_CONTAINERS}" != "**None**" ]; then
arr_keep_containers=$(echo ${KEEP_CONTAINERS} | tr "," "\n")
if [ "${KEEP_CONTAINERS}" == "**None**" ]; then
unset KEEP_CONTAINERS
fi
if [ "${KEEP_CONTAINERS}" == "**All**" ]; then
KEEP_CONTAINERS="."
fi
unset KEEP_CONTAINERS


if [ "${LOOP}" != "false" ]; then
LOOP=true
fi

if [ "${DEBUG}" == "0" ]; then
unset DEBUG
fi

if [ $DEBUG ]; then echo DEBUG ENABLED; fi

echo "=> Run the clean script every ${CLEAN_PERIOD} seconds and delay ${DELAY_TIME} seconds to clean."

trap '{ echo "User Interupt."; exit 1; }' SIGINT
trap '{ echo "SIGTERM received, exiting."; exit 0; }' SIGTERM
while [ 1 ]
do
if [ $DEBUG ]; then echo DEBUG: Starting loop; fi

# Cleanup unused volumes
echo "=> Removing unused volumes"
/docker-cleanup-volumes.sh

IFS='
'

# Cleanup exited/dead containers
echo "=> Removing exited/dead containers"
EXITED_CONTAINERS_IDS="`docker ps -a -q -f status=exited -f status=dead | xargs echo`"
for CONTAINER_ID in $EXITED_CONTAINERS_IDS; do
CONTAINER_IMAGE=$(docker inspect --format='{{(index .Config.Image)}}' $CONTAINER_ID)
if [[ ! "${arr_keep_containers[@]}" =~ "${CONTAINER_IMAGE}" ]]; then
echo "Removing container $CONTAINER_ID"
if [ $DEBUG ]; then echo "DEBUG: Check container $CONTAINER_IMAGE"; fi
keepit=0
if [ -n "${KEEP_CONTAINERS}" ]; then
for PATTERN in $(echo ${KEEP_CONTAINERS} | tr "," "\n"); do
if [[ "${CONTAINER_IMAGE}" = $PATTERN* ]]; then
if [ $DEBUG ]; then echo "DEBUG: Matches $PATTERN - keeping"; fi
keepit=1
else
if [ $DEBUG ]; then echo "DEBUG: No match for $PATTERN"; fi
fi
done
fi
if [[ $keepit -eq 0 ]]; then
echo "Removing stopped container $CONTAINER_ID"
docker rm -v $CONTAINER_ID
fi
done
unset CONTAINER_ID

echo "=> Removing unused images"

# Get all containers in "created" state
rm -f CreatedContainerIdList
docker ps -a -q -f status=created | sort > CreatedContainerIdList
Expand All @@ -67,8 +94,6 @@ do
ALL_LAYER_NUM=$(docker images -a | tail -n +2 | wc -l)
docker images -q --no-trunc | sort -o ImageIdList
CONTAINER_ID_LIST=$(docker ps -aq --no-trunc)
IFS='
'
# Get Image ID that is used by a containter
rm -f ContainerImageIdList
touch ContainerImageIdList
Expand All @@ -79,21 +104,42 @@ do
done
sort ContainerImageIdList -o ContainerImageIdList

# Remove the images being used by cotnainers from the delete list
# Remove the images being used by containers from the delete list
comm -23 ImageIdList ContainerImageIdList > ToBeCleanedImageIdList

# Remove those reserved images from the delete list
if [ -n "${KEEP_IMAGES}" ]; then
rm -f KeepImageIdList
touch KeepImageIdList
arr=$(echo ${KEEP_IMAGES} | tr "," "\n")
for x in $arr
do
docker inspect $x | grep "\"Id\": \"\(sha256:\)\?[0-9a-fA-F]\{64\}\"" | head -1 | awk -F '"' '{print $4}' >> KeepImageIdList
rm -f KeepImageIdList
touch KeepImageIdList
# This looks to see if anything matches the regexp
docker images --no-trunc | (
while read repo tag image junk; do
keepit=0
if [ $DEBUG ]; then echo "DEBUG: Check image $repo:$tag"; fi
for PATTERN in $(echo ${KEEP_IMAGES} | tr "," "\n"); do
if [[ -n "$PATTERN" && "${repo}:${tag}" = $PATTERN* ]]; then
if [ $DEBUG ]; then echo "DEBUG: Matches $PATTERN"; fi
keepit=1
else
if [ $DEBUG ]; then echo "DEBUG: No match for $PATTERN"; fi
fi
done
if [[ $keepit -eq 1 ]]; then
if [ $DEBUG ]; then echo "DEBUG: Marking image $repo:$tag to keep"; fi
echo $image >> KeepImageIdList
fi
done
sort KeepImageIdList -o KeepImageIdList
comm -23 ToBeCleanedImageIdList KeepImageIdList > ToBeCleanedImageIdList2
mv ToBeCleanedImageIdList2 ToBeCleanedImageIdList
)
# This explicitly looks for the images specified
arr=$(echo ${KEEP_IMAGES} | tr "," "\n")
for x in $arr
do
if [ $DEBUG ]; then echo "DEBUG: Identifying image $x"; fi
docker inspect $x 2>/dev/null| grep "\"Id\": \"\(sha256:\)\?[0-9a-fA-F]\{64\}\"" | head -1 | awk -F '"' '{print $4}' >> KeepImageIdList
done
sort KeepImageIdList -o KeepImageIdList
comm -23 ToBeCleanedImageIdList KeepImageIdList > ToBeCleanedImageIdList2
mv ToBeCleanedImageIdList2 ToBeCleanedImageIdList
fi

# Wait before cleaning containers and images
Expand All @@ -105,6 +151,7 @@ do
comm -12 CreatedContainerIdList <(docker ps -a -q -f status=created | sort) > CreatedContainerToClean
if [ -s CreatedContainerToClean ]; then
echo "=> Start to clean $(cat CreatedContainerToClean | wc -l) created/stuck containers"
if [ $DEBUG ]; then echo "DEBUG: Removing unstarted containers"; fi
docker rm -v $(cat CreatedContainerToClean)
fi

Expand Down