#!/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:-}" 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."