101 lines
3 KiB
Bash
101 lines
3 KiB
Bash
#!/usr/bin/env bash
|
|
#
|
|
# temp-env.sh
|
|
# Spin up a throwaway Debian container, install packages, drop into a shell,
|
|
# and clean up automatically when you exit.
|
|
|
|
set -euo pipefail
|
|
|
|
# ---- colors ----
|
|
BOLD='\033[1m'
|
|
CYAN='\033[0;36m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[0;33m'
|
|
RED='\033[0;31m'
|
|
NC='\033[0m'
|
|
|
|
info() { echo -e "${CYAN}==>${NC} $1"; }
|
|
ok() { echo -e "${GREEN}✔${NC} $1"; }
|
|
warn() { echo -e "${YELLOW}!${NC} $1"; }
|
|
err() { echo -e "${RED}✘${NC} $1"; }
|
|
|
|
# ---- sanity checks ----
|
|
if ! command -v docker &>/dev/null; then
|
|
err "Docker isn't installed or isn't on PATH."
|
|
exit 1
|
|
fi
|
|
|
|
echo -e "${BOLD}Ephemeral Debian Environment${NC}"
|
|
echo "--------------------------------"
|
|
|
|
# ---- pick a debian tag ----
|
|
read -rp "$(echo -e "${CYAN}?${NC} Debian tag [bookworm]: ")" TAG
|
|
TAG="${TAG:-bookworm}"
|
|
IMAGE="debian:${TAG}"
|
|
|
|
# ---- packages to install ----
|
|
read -rp "$(echo -e "${CYAN}?${NC} Packages to install (space-separated, blank for none): ")" PACKAGES
|
|
|
|
# ---- optional extra apt flags ----
|
|
read -rp "$(echo -e "${CYAN}?${NC} Extra apt-get flags (e.g. --no-install-recommends) [none]: ")" APT_FLAGS
|
|
|
|
# ---- mount a local dir? ----
|
|
read -rp "$(echo -e "${CYAN}?${NC} Mount a local directory into the container? (path or blank): ")" MOUNT_DIR
|
|
MOUNT_ARGS=()
|
|
if [[ -n "$MOUNT_DIR" ]]; then
|
|
if [[ -d "$MOUNT_DIR" ]]; then
|
|
MOUNT_ARGS=(-v "$(realpath "$MOUNT_DIR"):/mnt/host")
|
|
ok "Will mount $(realpath "$MOUNT_DIR") -> /mnt/host"
|
|
else
|
|
warn "Directory '$MOUNT_DIR' doesn't exist, skipping mount."
|
|
fi
|
|
fi
|
|
|
|
# ---- remove image after exit too? ----
|
|
read -rp "$(echo -e "${CYAN}?${NC} Remove the image (${IMAGE}) after exiting, not just the container? [y/N]: ")" RM_IMAGE
|
|
RM_IMAGE="${RM_IMAGE:-n}"
|
|
|
|
# ---- build the in-container command ----
|
|
if [[ -n "$PACKAGES" ]]; then
|
|
INNER_CMD="apt-get update && apt-get install -y ${APT_FLAGS} ${PACKAGES} && bash"
|
|
else
|
|
INNER_CMD="apt-get update && bash"
|
|
fi
|
|
|
|
echo
|
|
info "Image: ${IMAGE}"
|
|
info "Packages: ${PACKAGES:-<none>}"
|
|
info "Command: ${INNER_CMD}"
|
|
[[ -n "$MOUNT_DIR" && -d "$MOUNT_DIR" ]] && info "Mount: $(realpath "$MOUNT_DIR") -> /mnt/host"
|
|
echo
|
|
|
|
read -rp "$(echo -e "${CYAN}?${NC} Launch now? [Y/n]: ")" CONFIRM
|
|
CONFIRM="${CONFIRM:-y}"
|
|
if [[ ! "$CONFIRM" =~ ^[Yy] ]]; then
|
|
warn "Aborted."
|
|
exit 0
|
|
fi
|
|
|
|
info "Pulling/starting container (this shell disappears on exit, --rm is set)..."
|
|
echo "--------------------------------"
|
|
|
|
set +e
|
|
docker run --rm -it "${MOUNT_ARGS[@]}" "$IMAGE" bash -c "$INNER_CMD"
|
|
EXIT_CODE=$?
|
|
set -e
|
|
|
|
echo "--------------------------------"
|
|
ok "Container exited (code ${EXIT_CODE}) and was automatically removed."
|
|
|
|
if [[ "$RM_IMAGE" =~ ^[Yy] ]]; then
|
|
info "Checking if any other containers still use ${IMAGE}..."
|
|
IN_USE=$(docker ps -a --filter ancestor="$IMAGE" -q)
|
|
if [[ -n "$IN_USE" ]]; then
|
|
warn "Other containers still reference ${IMAGE}, skipping removal:"
|
|
docker ps -a --filter ancestor="$IMAGE"
|
|
else
|
|
docker rmi "$IMAGE" && ok "Removed image ${IMAGE}."
|
|
fi
|
|
fi
|
|
|
|
ok "Done."
|