301 lines
6.9 KiB
Bash
Executable File
301 lines
6.9 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# docker-clean.sh - Interactive Docker cleanup for the ByteLyst platform prototype.
|
|
set -euo pipefail
|
|
|
|
RED=$'\033[0;31m'
|
|
GREEN=$'\033[0;32m'
|
|
YELLOW=$'\033[1;33m'
|
|
CYAN=$'\033[0;36m'
|
|
BOLD=$'\033[1m'
|
|
DIM=$'\033[2m'
|
|
NC=$'\033[0m'
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
|
|
log() { echo -e "${CYAN}[docker-clean]${NC} $*"; }
|
|
ok() { echo -e "${GREEN}OK:${NC} $*"; }
|
|
warn() { echo -e "${YELLOW}WARN:${NC} $*"; }
|
|
err() { echo -e "${RED}ERROR:${NC} $*" >&2; }
|
|
|
|
require_docker() {
|
|
if ! command -v docker >/dev/null 2>&1; then
|
|
err "Docker CLI is not installed or not on PATH."
|
|
exit 1
|
|
fi
|
|
|
|
if ! docker info >/dev/null 2>&1; then
|
|
err "Docker daemon is not reachable. Start Docker Desktop or your Docker daemon and try again."
|
|
exit 1
|
|
fi
|
|
|
|
if ! docker compose version >/dev/null 2>&1; then
|
|
err "Docker Compose plugin is not available. Install/update Docker Desktop or the docker compose plugin."
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
run_cmd() {
|
|
echo -e "${DIM}$*${NC}"
|
|
"$@"
|
|
}
|
|
|
|
confirm() {
|
|
local prompt="$1"
|
|
read -r -p "$(echo -e "${BOLD}${prompt}${NC} [y/N] ")" answer
|
|
case "${answer:-}" in
|
|
y|Y|yes|YES) return 0 ;;
|
|
* ) return 1 ;;
|
|
esac
|
|
}
|
|
|
|
compose_status() {
|
|
log "Compose services in $REPO_ROOT"
|
|
cd "$REPO_ROOT"
|
|
run_cmd docker compose ps
|
|
echo ""
|
|
log "Docker disk usage"
|
|
run_cmd docker system df
|
|
}
|
|
|
|
stop_compose() {
|
|
log "Stopping compose services"
|
|
cd "$REPO_ROOT"
|
|
run_cmd docker compose stop
|
|
}
|
|
|
|
down_compose() {
|
|
log "Removing compose containers and networks"
|
|
cd "$REPO_ROOT"
|
|
run_cmd docker compose down --remove-orphans
|
|
}
|
|
|
|
down_compose_with_volumes() {
|
|
cd "$REPO_ROOT"
|
|
run_cmd docker compose down --remove-orphans --volumes
|
|
}
|
|
|
|
safe_prune() {
|
|
log "Pruning stopped containers, unused networks, dangling images, and build cache"
|
|
run_cmd docker container prune --force
|
|
run_cmd docker network prune --force
|
|
run_cmd docker image prune --force
|
|
run_cmd docker builder prune --force
|
|
}
|
|
|
|
unused_image_prune() {
|
|
run_cmd docker image prune --all --force
|
|
run_cmd docker builder prune --all --force
|
|
}
|
|
|
|
full_prune() {
|
|
run_cmd docker system prune --all --volumes --force
|
|
}
|
|
|
|
builder_prune() {
|
|
log "Pruning Docker builder cache"
|
|
run_cmd docker builder prune --all --force
|
|
}
|
|
|
|
show_menu() {
|
|
cat <<EOF
|
|
|
|
${BOLD}Docker Cleanup Menu${NC}
|
|
|
|
Repo: $REPO_ROOT
|
|
|
|
${BOLD}1${NC}) Status only
|
|
Show compose services and Docker disk usage.
|
|
|
|
${BOLD}2${NC}) Stop compose services
|
|
Keeps containers, networks, volumes, and images.
|
|
|
|
${BOLD}3${NC}) Remove compose containers and networks
|
|
Runs compose down with orphan cleanup. Keeps repo volumes.
|
|
|
|
${BOLD}4${NC}) Remove compose containers, networks, and repo compose volumes
|
|
Deletes prototype state for this repo's compose project.
|
|
|
|
${BOLD}5${NC}) Safe global prune
|
|
Removes stopped containers, unused networks, dangling images, and build cache.
|
|
|
|
${BOLD}6${NC}) Deeper image/cache prune
|
|
Removes all unused images and build cache.
|
|
|
|
${BOLD}7${NC}) Full global Docker prune
|
|
Removes all unused Docker resources, including unused volumes.
|
|
|
|
${BOLD}8${NC}) Builder cache only
|
|
Removes Docker build cache.
|
|
|
|
${BOLD}q${NC}) Quit
|
|
|
|
EOF
|
|
}
|
|
|
|
describe_level() {
|
|
case "$1" in
|
|
1)
|
|
cat <<EOF
|
|
|
|
${BOLD}You selected: Status only${NC}
|
|
|
|
This will:
|
|
- Show this repo's Docker Compose services.
|
|
- Show Docker disk usage.
|
|
- Not stop, remove, or prune anything.
|
|
|
|
After this, everything will remain exactly as it is.
|
|
EOF
|
|
;;
|
|
2)
|
|
cat <<EOF
|
|
|
|
${BOLD}You selected: Stop compose services${NC}
|
|
|
|
This will:
|
|
- Stop containers from this repo's Docker Compose stack.
|
|
- Keep the containers, networks, images, and volumes.
|
|
- Preserve prototype data in Cosmos, Azurite, and Mailpit volumes.
|
|
|
|
After this, the stack will be stopped but can be resumed with:
|
|
./scripts/prototype-up.sh
|
|
EOF
|
|
;;
|
|
3)
|
|
cat <<EOF
|
|
|
|
${BOLD}You selected: Remove compose containers and networks${NC}
|
|
|
|
This will:
|
|
- Stop and remove this repo's compose containers.
|
|
- Remove compose networks and orphan containers.
|
|
- Keep repo compose volumes.
|
|
- Preserve prototype data in Cosmos, Azurite, and Mailpit volumes.
|
|
|
|
After this, containers will be recreated the next time you start the prototype.
|
|
EOF
|
|
;;
|
|
4)
|
|
cat <<EOF
|
|
|
|
${BOLD}You selected: Remove compose containers, networks, and repo compose volumes${NC}
|
|
|
|
This will:
|
|
- Stop and remove this repo's compose containers.
|
|
- Remove compose networks and orphan containers.
|
|
- Delete this repo's compose volumes.
|
|
- Delete prototype state stored in local Cosmos, Azurite, and Mailpit volumes.
|
|
|
|
After this, the next prototype start will recreate empty local backing services.
|
|
EOF
|
|
;;
|
|
5)
|
|
cat <<EOF
|
|
|
|
${BOLD}You selected: Safe global prune${NC}
|
|
|
|
This will:
|
|
- Remove all stopped Docker containers.
|
|
- Remove unused Docker networks.
|
|
- Remove dangling image layers.
|
|
- Remove unused Docker build cache.
|
|
- Keep named volumes.
|
|
- Keep images that are still tagged or used by containers.
|
|
|
|
After this, Docker should use less disk space while preserving volumes.
|
|
EOF
|
|
;;
|
|
6)
|
|
cat <<EOF
|
|
|
|
${BOLD}You selected: Deeper image/cache prune${NC}
|
|
|
|
This will:
|
|
- Remove all unused Docker images, not just dangling layers.
|
|
- Remove all unused Docker build cache.
|
|
- Keep images used by existing containers.
|
|
- Keep named volumes.
|
|
|
|
After this, future builds and starts may need to pull or rebuild images.
|
|
EOF
|
|
;;
|
|
7)
|
|
cat <<EOF
|
|
|
|
${BOLD}You selected: Full global Docker prune${NC}
|
|
|
|
This will:
|
|
- Remove stopped containers across Docker.
|
|
- Remove unused networks across Docker.
|
|
- Remove all unused images.
|
|
- Remove build cache.
|
|
- Remove all unused volumes, including volumes from other projects if Docker considers them unused.
|
|
|
|
After this, Docker disk usage should drop the most, but other local projects may need to recreate data volumes.
|
|
EOF
|
|
;;
|
|
8)
|
|
cat <<EOF
|
|
|
|
${BOLD}You selected: Builder cache only${NC}
|
|
|
|
This will:
|
|
- Remove Docker build cache.
|
|
- Keep containers, images, networks, and volumes.
|
|
|
|
After this, future Docker builds may be slower until the cache is rebuilt.
|
|
EOF
|
|
;;
|
|
q|Q)
|
|
exit 0
|
|
;;
|
|
*)
|
|
err "Unknown cleanup level: $1"
|
|
return 1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
run_level() {
|
|
case "$1" in
|
|
1) compose_status ;;
|
|
2) stop_compose ;;
|
|
3) down_compose ;;
|
|
4) down_compose_with_volumes ;;
|
|
5) safe_prune ;;
|
|
6) unused_image_prune ;;
|
|
7) full_prune ;;
|
|
8) builder_prune ;;
|
|
q|Q) exit 0 ;;
|
|
*) err "Unknown cleanup level: $1"; exit 1 ;;
|
|
esac
|
|
}
|
|
|
|
if [[ $# -gt 0 ]]; then
|
|
warn "This script is interactive and does not accept CLI parameters. Ignoring: $*"
|
|
fi
|
|
|
|
show_menu
|
|
read -r -p "Select cleanup level: " LEVEL
|
|
describe_level "${LEVEL:-q}"
|
|
|
|
if [[ "${LEVEL:-q}" == "1" ]]; then
|
|
echo ""
|
|
require_docker
|
|
run_level "$LEVEL"
|
|
ok "Done."
|
|
exit 0
|
|
fi
|
|
|
|
echo ""
|
|
if ! confirm "Proceed with this cleanup?"; then
|
|
warn "Cancelled. No cleanup was performed."
|
|
exit 0
|
|
fi
|
|
|
|
echo ""
|
|
require_docker
|
|
run_level "${LEVEL:-q}"
|
|
ok "Done."
|