Files
homelab/cleanup-docker-disk-space.sh
T
2023-11-17 23:49:09 -08:00

155 lines
3.8 KiB
Bash
Executable File

#!/usr/bin/env bash
# Set shell options:
# -e, exit immediately if a command exits with a non-zero status
# -o pipefail, means that if any element of the pipeline fails, then the pipeline as a whole will fail.
# -u, treat unset variables as an error when substituting.
set -e
set -u
set -o pipefail
DONT_RESTART_DOCKER_ENGINE=0
DONT_ASK_CONFIRMATION=0
while [[ $# -gt 0 ]]; do
key="$1"
case $key in
--no-restart)
DONT_RESTART_DOCKER_ENGINE=1
shift
;;
-y)
DONT_ASK_CONFIRMATION=1
shift
;;
*)
echo "Unknown parameter passed: $1";
exit 1;
;;
esac
done
# Asks user for confirmation interactively
ask_user_for_confirmation () {
cat << EOF
==============================================
This script reclaims disk space by removing stale and unused Docker data:
> removes stopped containers
> removes orphan (dangling) images layers
> removes unused volumes
> removes Docker build cache
> shrinks the "Docker.raw" file on MacOS
> restarts the Docker engine
> prints Docker disk usage
==============================================
EOF
if [ $DONT_ASK_CONFIRMATION -eq 1 ]; then
return
fi
read -p "Would you like to proceed (y/n)? " confirmation
# Stop if answer is anything but "Y" or "y"
if [ "$confirmation" == "${confirmation#[Yy]}" ]; then
exit 1;
fi
}
# On MacOS, restarting Docker Desktop for Mac might take a long time
poll_for_docker_readiness() {
# TODO: add new line at the end of polling
printf 'Waiting for docker engine to start:\n'
local i=0
while ! docker system info > /dev/null 2>&1;
do
printf '.%.0s' {1..$i}
i=$((i + 1))
sleep 1
tput el
done
printf '\n'
}
# Checks if a particular program is installed
is_program_installed () {
command -v "$1" &>/dev/null
}
# Restarts the Docker engine
restart_docker_engine () {
if [ $DONT_RESTART_DOCKER_ENGINE -eq 1 ]; then
return
fi
echo "👉 Restarting Docker engine"
# On MacOS, restart through "launchd"
if [ "$(uname)" == "Darwin" ] && is_program_installed "launchctl"; then
local docker_service=$(launchctl list | grep "com.docker.docker" | awk '$0 != "-" { print $3 }')
if [ -n "$docker_service" ]; then
launchctl stop "$docker_service" || true;
fi
launchctl start com.docker.helper
sleep 1
poll_for_docker_readiness
# On Linux, restart through "systemd"
elif [ "$(uname)" == "Linux" ] && is_program_installed "systemctl"; then
sudo systemctl stop snap.docker.dockerd.service || true
sudo systemctl start snap.docker.dockerd.service
# Other platforms are not supported
else
printf "Platform type $(uname) is not supported\n" >&2
fi
}
echo "👉 Docker disk usage"
docker system df
ask_user_for_confirmation
echo "👉 Remove all stopped containers"
docker ps --filter "status=exited" -q | xargs -r docker rm --force
echo "👉 Remove all orphan image layers"
docker images -f "dangling=true" -q | xargs -r docker rmi -f
echo "👉 Remove all unused volumes"
docker volume ls -qf dangling=true | xargs -r docker volume rm
echo "👉 Remove Docker builder cache"
DOCKER_BUILDKIT=1 docker builder prune --all --force
echo "👉 Remove docker builder cache"
echo "👉 Remove networks not used by at least one container"
docker network prune --force
# echo "👉 Remove unused volumes"
# -a, --all, Remove all unused build cache, not just dangling ones
# docker system prune --force --volumes
# Run "docker/docker-reclaim-space" only on Intel chips
# because image is not build for ARM achitecture (Apple M1 chips)
if [ "$(uname)" == "Darwin" ] && [ "$(uname -m)" == "x86_64" ]; then
echo "👉 Shrink the Docker.raw file"
docker run --privileged --pid=host docker/desktop-reclaim-space
fi
echo "👉 Docker disk usage (after cleanup)"
docker system df
restart_docker_engine
echo "🤘 Done"