Skip to content

Commit 5e2f553

Browse files
authored
Update cleanup_unused_images.sh
1 parent 7ca9ac0 commit 5e2f553

1 file changed

Lines changed: 81 additions & 16 deletions

File tree

Lines changed: 81 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,21 @@
11
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
# ================================
5+
# Docker Swarm Cluster Cleanup Script
6+
# ================================
7+
# Features:
8+
# --dry-run Preview cleanup (default if no flag is provided)
9+
# --live Actually prune images
10+
# --dangling-only Remove ONLY dangling (<none>) images
11+
# --all Remove ALL unused images (default for live)
12+
# --confirm CLEAN Skip interactive confirmation (cron-friendly)
13+
#
14+
# Usage examples:
15+
# ./cleanup_unused_images.sh --dry-run
16+
# ./cleanup_unused_images.sh --live --dangling-only
17+
# ./cleanup_unused_images.sh --live --all --confirm CLEAN
18+
# =================================
219

320
# List of all your Swarm nodes
421
NODES=(
@@ -10,38 +27,86 @@ NODES=(
1027
"docker-prod-worker3"
1128
)
1229

30+
MODE="dry-run"
31+
PRUNE_TYPE="all"
32+
CONFIRM_INPUT=""
33+
34+
# ===== Parse Flags =====
35+
while [[ $# -gt 0 ]]; do
36+
case "$1" in
37+
--dry-run) MODE="dry-run" ;;
38+
--live) MODE="live" ;;
39+
--dangling-only) PRUNE_TYPE="dangling" ;;
40+
--all) PRUNE_TYPE="all" ;;
41+
--confirm) CONFIRM_INPUT="${2:-}"; shift ;;
42+
*) echo "❌ Unknown option: $1"; exit 1 ;;
43+
esac
44+
shift
45+
done
46+
47+
LOGFILE="./docker_cleanup_$(date +%F).log"
48+
exec > >(tee -a "$LOGFILE") 2>&1
49+
1350
echo "=== Docker Swarm Cluster Cleanup ==="
14-
echo "This script will connect to each node and prune unused images."
51+
echo "Mode: $MODE"
52+
echo "Prune type: $PRUNE_TYPE"
53+
echo "Nodes: ${#NODES[@]}"
54+
echo "Logs: $LOGFILE"
1555
echo "-------------------------------------"
1656

17-
# First, show disk usage before cleanup
57+
# Pick correct prune command
58+
if [[ "$PRUNE_TYPE" == "dangling" ]]; then
59+
PRUNE_CMD="sudo docker image prune -f"
60+
else
61+
PRUNE_CMD="sudo docker image prune -a -f"
62+
fi
63+
64+
# Step 1: Show disk usage before cleanup
1865
for NODE in "${NODES[@]}"; do
1966
echo "---- $NODE: Disk usage before ----"
20-
ssh serveradmin@$NODE "sudo docker system df"
67+
ssh -o BatchMode=yes serveradmin@"$NODE" "sudo docker system df || true"
2168
done
2269

23-
# Then show which images will be removed (manual preview since there's no --dry-run)
70+
# Step 2: Preview images that *would* be removed
71+
echo "---- DRY-RUN PREVIEW ----"
2472
for NODE in "${NODES[@]}"; do
25-
echo "---- $NODE: Dangling images preview ----"
26-
ssh serveradmin@$NODE "sudo docker images -f 'dangling=true'"
73+
echo "Node: $NODE"
74+
ssh -o BatchMode=yes serveradmin@"$NODE" "
75+
echo 'Dangling Images:' &&
76+
sudo docker images -f 'dangling=true' --format '{{.Repository}}:{{.Tag}} {{.ID}} {{.Size}}' || true
77+
echo '---'
78+
if [[ \"$PRUNE_TYPE\" == \"all\" ]]; then
79+
echo 'Unused Tagged Images:' &&
80+
sudo docker images --filter 'dangling=false' --format '{{.Repository}}:{{.Tag}} {{.ID}} {{.Size}}' |
81+
grep -v '<none>' || echo 'None'
82+
else
83+
echo '(Skipping unused tagged images: dangling-only mode)'
84+
fi
85+
"
2786
done
2887

29-
read -rp "Proceed to prune unused images on all nodes? (y/N): " CONFIRM
30-
if [[ "$CONFIRM" != "y" && "$CONFIRM" != "Y" ]]; then
31-
echo "Aborted."
32-
exit 1
88+
# If dry-run, exit safely
89+
if [[ "$MODE" == "dry-run" ]]; then
90+
echo "✅ Dry-run complete. No images were deleted."
91+
exit 0
92+
fi
93+
94+
# Step 3: If live mode, require confirmation
95+
if [[ "$CONFIRM_INPUT" != "CLEAN" ]]; then
96+
read -rp "⚠️ Type CLEAN to prune images across ALL nodes: " CONFIRM_INPUT
97+
[[ "$CONFIRM_INPUT" != "CLEAN" ]] && echo "Aborted." && exit 1
3398
fi
3499

35-
# Run actual prune
100+
# Step 4: Run prune command on all nodes
36101
for NODE in "${NODES[@]}"; do
37-
echo "---- $NODE: Pruning unused images ----"
38-
ssh serveradmin@$NODE "sudo docker image prune -a -f"
102+
echo "---- $NODE: Pruning images ----"
103+
ssh -o BatchMode=yes serveradmin@"$NODE" "$PRUNE_CMD || true"
39104
done
40105

41-
# Show disk usage after cleanup
106+
# Step 5: Show disk usage after cleanup
42107
for NODE in "${NODES[@]}"; do
43108
echo "---- $NODE: Disk usage after ----"
44-
ssh serveradmin@$NODE "sudo docker system df"
109+
ssh -o BatchMode=yes serveradmin@"$NODE" "sudo docker system df || true"
45110
done
46111

47-
echo "✅ Done! All unused images have been cleaned up across the cluster."
112+
echo "✅ Done! Cleanup complete. Logs saved to $LOGFILE"

0 commit comments

Comments
 (0)