Skip to content
Open
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
85 changes: 43 additions & 42 deletions docker-cleanup-volumes.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ docker_bin=$(which docker.io 2> /dev/null || which docker 2> /dev/null)
dockerdir=/var/lib/docker

# Look for an alternate docker directory with -g option
dockerPs=`ps aux | grep $docker_bin | grep -v grep` || :
if [[ $dockerPs =~ ' -g ' ]]; then
dockerdir=`echo $dockerPs | sed 's/.* -g//' | cut -d ' ' -f 2`

dockerPs=$(tr "\0" " " < "/proc/$(pgrep "$docker_bin")/cmdline") || :
if [[ $dockerPs =~ -g ]]; then
dockerdir=$(echo "$dockerPs" | sed 's/.* -g//' | cut -d ' ' -f 2)
fi

volumesdir=${dockerdir}/volumes
Expand All @@ -24,28 +25,29 @@ function delete_volumes() {
targetdir=$1
echo
if [[ ! -d ${targetdir} ]]; then
echo "Directory ${targetdir} does not exist, skipping."
return
fi
echo "Delete unused volume directories from $targetdir"
for dir in $(ls -d ${targetdir}/* 2>/dev/null)
do
dir=$(basename $dir)
if [[ "${dir}" =~ [0-9a-f]{64} ]]; then
if [ ${#allvolumes[@]} -gt 0 ] && [[ ${allvolumes[@]} =~ "${dir}" ]]; then
echo In use ${dir}
else
if [ "${dryrun}" = false ]; then
echo Deleting ${dir}
rm -rf ${targetdir}/${dir}
else
echo Would have deleted ${dir}
fi
fi
echo "Directory ${targetdir} does not exist, skipping."
return
fi
echo "Delete unused volume directories from $targetdir"
for dir in ${targetdir}/*
do
[[ -e $dir ]] || break
dir=$(basename "$dir")
if [[ "${dir}" =~ [0-9a-f]{64} ]]; then
if [ ${#allvolumes[@]} -gt 0 ] && [[ ${allvolumes[@]} =~ ${dir} ]]; then
echo "In use ${dir}"
else
echo Not a volume ${dir}
if [ "${dryrun}" = false ]; then
echo "Deleting ${dir}"
rm -rf "${targetdir:?}/${dir:?}"
else
echo "Would have deleted ${dir}"
fi
fi
done
else
echo "Not a volume ${dir}"
fi
done
}

if [ $UID != 0 ]; then
Expand All @@ -59,13 +61,12 @@ if [ -z "$docker_bin" ] ; then
fi

if [ $# -gt 0 ] && [ "$1" = "--dry-run" ]; then
dryrun=true
else if [ $# -gt 0 ] && [ -n "$1" ]; then
echo "Cleanup docker volumes: remove unused volumes."
echo "Usage: ${0##*/} [--dry-run]"
echo " --dry-run: dry run: display what would get removed."
exit 1
fi
dryrun=true
elif [ $# -gt 0 ] && [ -n "$1" ]; then
echo "Cleanup docker volumes: remove unused volumes."
echo "Usage: ${0##*/} [--dry-run]"
echo " --dry-run: dry run: display what would get removed."
exit 1
fi

# Make sure that we can talk to docker daemon. If we cannot, we fail here.
Expand All @@ -76,7 +77,7 @@ container_ids=$(${docker_bin} ps -a -q --no-trunc)
# Check if we're running as a docker container
if [[ ${container_ids[@]} =~ (^|[[:space:]])"$HOSTNAME" ]]; then
# Get the dockerdir on the host from the volume mapped to /var/lib/docker
dockerdir_match=`${docker_bin} inspect -f '{{ index .Volumes "/var/lib/docker" }}' $HOSTNAME`
dockerdir_match=$(${docker_bin} inspect -f '{{ index .Volumes "/var/lib/docker" }}' "$HOSTNAME")
else
# Script is running standalone, dockerdir is the directory to use
dockerdir_match=${dockerdir}
Expand All @@ -92,24 +93,24 @@ for container in $container_ids; do
#ever exists in the volumesdir but just to be safe
allvolumes+=${container}
#add all volumes from this container to the list of volumes
for volpath in `${docker_bin} inspect --format='{{range $vol, $path := .Volumes}}{{$path}}{{"\n"}}{{end}}' ${container}`; do
for volpath in $(${docker_bin} inspect --format="{{range \$vol, \$path := .Volumes}}{{\$path}}{{\"\n\"}}{{end}}" "${container}"); do
#try to get volume id from the volume path
vid=$(echo "${volpath}"|sed "s|${vfsdir_match}||;s|${volumesdir_match}||;s/.*\([0-9a-f]\{64\}\).*/\1/")
# host daemon shows original dir path - this is why _match variables are used:
if [[ (${volpath} == ${vfsdir_match}* || ${volpath} == ${volumesdir_match}*) && "${vid}" =~ [0-9a-f]{64} ]]; then
allvolumes+=("${vid}")
allvolumes+=("${vid}")
else
#check if it's a bindmount, these have a config.json file in the ${volumesdir} but no files in ${vfsdir} (docker 1.6.2 and below)
for bmv in `grep --include config.json -Rl "\"IsBindMount\":true" ${volumesdir} | xargs grep -l "\"Path\":\"${volpath}\""`; do
bmv="$(basename "$(dirname "${bmv}")")"
allvolumes+=("${bmv}")
for bmv in $(grep --include config.json -Rl "\"IsBindMount\":true" "${volumesdir}" | xargs grep -l "\"Path\":\"${volpath}\""); do
bmv="$(basename "$(dirname "${bmv}")")"
allvolumes+=("${bmv}")
#there should be only one config for the bindmount, delete any duplicate for the same bindmount.
break
done
fi
done
done
done
fi
done
done

delete_volumes ${volumesdir}
delete_volumes ${vfsdir}
delete_volumes "${volumesdir}"
delete_volumes "${vfsdir}"