chore(docker): add interactive cleanup menu
This commit is contained in:
parent
8f449a5ee5
commit
e619fa8eb5
@ -39,6 +39,7 @@ For a single-host prototype, use Docker Compose with the repo root [`docker-comp
|
|||||||
cp .env.example .env
|
cp .env.example .env
|
||||||
./scripts/prototype-up.sh
|
./scripts/prototype-up.sh
|
||||||
pnpm prototype:self-test
|
pnpm prototype:self-test
|
||||||
|
pnpm docker:clean
|
||||||
```
|
```
|
||||||
|
|
||||||
See [docs/PROTOTYPE_DEPLOYMENT.md](docs/PROTOTYPE_DEPLOYMENT.md) for the required environment variables and day-to-day commands.
|
See [docs/PROTOTYPE_DEPLOYMENT.md](docs/PROTOTYPE_DEPLOYMENT.md) for the required environment variables and day-to-day commands.
|
||||||
|
|||||||
@ -65,10 +65,13 @@ docker compose logs -f mailpit
|
|||||||
pnpm prototype:self-test
|
pnpm prototype:self-test
|
||||||
./scripts/prototype-self-test.sh
|
./scripts/prototype-self-test.sh
|
||||||
docker compose down
|
docker compose down
|
||||||
|
pnpm docker:clean
|
||||||
```
|
```
|
||||||
|
|
||||||
`pnpm prototype:self-test` is the stable host-side smoke-test entrypoint. It runs the same end-to-end check as the underlying shell script, but gives ops a single repo-level command to remember.
|
`pnpm prototype:self-test` is the stable host-side smoke-test entrypoint. It runs the same end-to-end check as the underlying shell script, but gives ops a single repo-level command to remember.
|
||||||
|
|
||||||
|
`pnpm docker:clean` opens an interactive Docker cleanup menu. Use it for escalating cleanup levels from status-only and compose shutdown through repo volume cleanup, image pruning, and full Docker volume pruning.
|
||||||
|
|
||||||
The Cosmos Data Explorer is exposed on `http://localhost:1234`.
|
The Cosmos Data Explorer is exposed on `http://localhost:1234`.
|
||||||
Azurite Blob Storage is exposed on `http://localhost:10000`.
|
Azurite Blob Storage is exposed on `http://localhost:10000`.
|
||||||
Mailpit SMTP listens on `localhost:1025` and the Mailpit inbox UI is exposed on `http://localhost:8025`.
|
Mailpit SMTP listens on `localhost:1025` and the Mailpit inbox UI is exposed on `http://localhost:8025`.
|
||||||
|
|||||||
@ -18,6 +18,7 @@
|
|||||||
"format:check": "prettier --check \"**/*.{ts,tsx,js,jsx,json,md,yml,yaml}\"",
|
"format:check": "prettier --check \"**/*.{ts,tsx,js,jsx,json,md,yml,yaml}\"",
|
||||||
"audit": "pnpm -r audit --audit-level moderate",
|
"audit": "pnpm -r audit --audit-level moderate",
|
||||||
"clean": "pnpm -r exec rm -rf dist",
|
"clean": "pnpm -r exec rm -rf dist",
|
||||||
|
"docker:clean": "./scripts/docker-clean.sh",
|
||||||
"dns:godaddy:bytelyst": "./scripts/godaddy-sync-bytelyst-dns.sh",
|
"dns:godaddy:bytelyst": "./scripts/godaddy-sync-bytelyst-dns.sh",
|
||||||
"prototype:self-test": "./scripts/prototype-self-test.sh",
|
"prototype:self-test": "./scripts/prototype-self-test.sh",
|
||||||
"release": "./scripts/gitea/release-packages.sh",
|
"release": "./scripts/gitea/release-packages.sh",
|
||||||
|
|||||||
300
scripts/docker-clean.sh
Executable file
300
scripts/docker-clean.sh
Executable file
@ -0,0 +1,300 @@
|
|||||||
|
#!/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."
|
||||||
Loading…
Reference in New Issue
Block a user