11#! /usr/bin/env bash
2- set -u # only fail on unset vars
2+ set -euo pipefail
33
4+ # configurable cutoff
45CUTOFF_HOURS=${CUTOFF_HOURS:- 24}
5- # always compute cutoff in UTC for comparison
6- CUTOFF_TS=$( date -u -d " ${CUTOFF_HOURS} hours ago" +%s 2> /dev/null || \
7- date -u -v-" ${CUTOFF_HOURS} " H +%s)
6+ CUTOFF_TS=$( date -u -d " ${CUTOFF_HOURS} hours ago" +%s 2> /dev/null || date -u -v-" ${CUTOFF_HOURS} " H +%s)
87
98echo " === Docker disk usage before cleanup ==="
10- docker system df -v || echo " (warning: docker system df failed) "
9+ docker system df -v || true
1110echo
1211
13- echo " === Checking images older than ${CUTOFF_HOURS} h (UTC-based) ==="
14-
1512deleted=0
1613kept=0
1714
18- while IFS= read -r line; do
19- id=$( awk ' {print $1}' <<< " $line" )
20- name=$( awk ' {print $2}' <<< " $line" )
21- created_at=$( awk ' {$1=$2=""; print substr($0,3)}' <<< " $line" )
15+ echo " === Checking images older than ${CUTOFF_HOURS} h (UTC) ==="
16+
17+ docker images --format ' {{json .}}' | while read -r json; do
18+ id=$( jq -r ' .ID' <<< " $json" )
19+ repo=$( jq -r ' .Repository' <<< " $json" )
20+ tag=$( jq -r ' .Tag' <<< " $json" )
21+ created_at=$( jq -r ' .CreatedAt' <<< " $json" )
2222
23+ # Skip empty or invalid
2324 [ -z " $id " ] && continue
24- [ " $name " = " <none>:<none>" ] && continue
2525
26- # parse docker UTC timestamp safely
27- created_ts=$( date -u -d " $created_at " +%s 2> /dev/null || echo 0)
26+ # Normalize name
27+ name=" ${repo} :${tag} "
28+
29+ # Convert CreatedAt → epoch (cross-platform)
30+ if date --version > /dev/null 2>&1 ; then
31+ created_ts=$( date -u -d " $created_at " +%s)
32+ else
33+ created_ts=$( date -u -j -f " %Y-%m-%d %H:%M:%S %z %Z" " $created_at " +%s)
34+ fi
2835
36+ # Compare
2937 if [ " $created_ts " -lt " $CUTOFF_TS " ]; then
30- echo " 🗑️ Removing old image: $name (created $created_at UTC )"
38+ echo " 🗑️ Removing old image: $name (created $created_at )"
3139 if docker rmi -f " $id " > /dev/null 2>&1 ; then
3240 deleted=$(( deleted+ 1 ))
3341 else
@@ -36,7 +44,7 @@ while IFS= read -r line; do
3644 else
3745 kept=$(( kept+ 1 ))
3846 fi
39- done < <( docker images --format ' {{.ID}} {{.Repository}}:{{.Tag}} {{.CreatedAt}} ' 2> /dev/null || true )
47+ done
4048
4149echo
4250echo " === Cleanup summary ==="
@@ -45,8 +53,8 @@ echo "Images deleted: $deleted"
4553echo
4654
4755echo " === Docker disk usage after cleanup ==="
48- docker system df -v || echo " (warning: docker system df failed) "
56+ docker system df -v || true
4957
5058echo
51- echo " === Host disk space ( for /var/lib/docker) ==="
59+ echo " === Disk space for /var/lib/docker ==="
5260df -h /var/lib/docker 2> /dev/null || df -h /
0 commit comments