#!/usr/bin/env bash # http://redsymbol.net/articles/unofficial-bash-strict-mode/ ######################################################################################### # SCRIPT: clear-docker-cache.sh # Description: Used to cleanup unused docker containers and volumes ###################################################################################### IFS=$'\n\t' set -euo pipefail if ! [ -x "$(command -v docker)" ]; then echo -e "INFO: Docker installation not found, skipping clear-docker-cache" exit 0 fi DOCKER_API_VERSION=$(docker version --format '{{.Client.APIVersion}}') DOCKER_CLIENT_VERSION=$(docker version --format '{{.Client.Version}}') REQUIRED_DOCKER_API_VERSION=1.25 FILTER_FLAG='label=com.gitlab.gitlab-runner.managed=true' usage() { echo -e "\nUsage: $0 prune-volumes|prune|space|help\n" echo -e "\tprune-volumes Remove all unused containers (both dangling and unreferenced) and volumes" echo -e "\tprune Remove all unused containers (both dangling and unreferenced)" echo -e "\tspace Show docker disk usage" echo -e "\thelp Show usage" exit 1 } if awk "BEGIN {exit !(\"$DOCKER_API_VERSION\" < \"$REQUIRED_DOCKER_API_VERSION\")}"; then echo -e "ERROR: Your current API version is lower than ${REQUIRED_DOCKER_API_VERSION}. The client and daemon API must both be at least ${REQUIRED_DOCKER_API_VERSION}+ to run these commands. Kindly upgrade your docker version." exit 1 fi # Docker 23.0 changed the existing `docker system prune` behaviour, and the workaround # for now is to fallback to the older behaviour by explicitly specifying the older API # version: https://github.com/docker/cli/issues/4028#issuecomment-1429538145 # We should be able to use DOCKER_API_VERSION 1.41, as this problem was only introduced # in Docker 23.0 which uses 1.42. PRUNE_DOCKER_API_VERSION=$DOCKER_API_VERSION if awk "BEGIN {exit !(\"$DOCKER_API_VERSION\" > \"1.41\")}"; then PRUNE_DOCKER_API_VERSION=1.41 fi COMMAND="${1:-prune-volumes}" case "$COMMAND" in prune) echo -e "\nCheck and remove all unused containers (both dangling and unreferenced)" echo -e "-----------------------------------------------------------------------" if awk "BEGIN {exit !(\"$DOCKER_CLIENT_VERSION\" < \"17.06.1\")}"; then # The docker system prune command without pruning volumes does not exist before 17.06.1, so we need to use docker rm CONTAINERS=$(docker ps -a -q \ --filter=status=exited \ --filter=status=dead \ --filter="$FILTER_FLAG") if [ -n "${CONTAINERS}" ]; then docker rm "${CONTAINERS}" fi else DOCKER_API_VERSION=$PRUNE_DOCKER_API_VERSION docker system prune -af --filter "$FILTER_FLAG" fi exit 0 ;; space) echo -e "\nShow docker disk usage" echo -e "----------------------" docker system df exit 0 ;; help) usage ;; prune-volumes) echo -e "\nCheck and remove all unused containers (both dangling and unreferenced) including volumes." echo -e "------------------------------------------------------------------------------------------" VOLUMES_FLAG='--volumes' if awk "BEGIN {exit !(\"$DOCKER_CLIENT_VERSION\" < \"17.06.1\")}"; then # The --volumes flag is not supported before 17.06.1 (it was implicit in those versions), so we need to remove the --volumes flag in that case VOLUMES_FLAG='' if awk "BEGIN {exit !(\"$DOCKER_CLIENT_VERSION\" < \"17.04.0\")}"; then # The --filter flag is not supported in docker system prune before 17.04.0, so we need to use docker rm CONTAINERS=$(docker ps -a -q \ --filter=status=exited \ --filter=status=dead \ --filter="$FILTER_FLAG") if [ -n "${CONTAINERS}" ]; then docker rm -v "${CONTAINERS}" fi exit 0 fi fi DOCKER_API_VERSION=$PRUNE_DOCKER_API_VERSION docker system prune "$VOLUMES_FLAG" -af --filter "$FILTER_FLAG" exit 0 ;; esac