#!/usr/bin/env bash set -euo pipefail # POS: docker vbox — Disposable Docker-based VMs (create/enter/start/stop/rm/ls) # POS_SUBCMDS: create enter stop start rm ls source "$(dirname "$0")/../lib/common.sh" 2>/dev/null || source "$(dirname "$0")/common.sh" usage() { cat < [image] [--dir ] pos docker vbox enter pos docker vbox stop pos docker vbox start pos docker vbox rm pos docker vbox ls Manage disposable Docker containers as lightweight VMs. Each container gets a bind-mounted host directory so files persist on the host even after the container is removed. Options: --dir Use custom directory instead of default ~/ Use "." for current directory Examples: pos docker vbox create lab1 pos docker vbox create lab1 --dir . pos docker vbox create lab1 --dir /mnt/data/lab1 pos docker vbox create kali kalilinux/kali-rolling pos docker vbox enter lab1 pos docker vbox stop lab1 pos docker vbox start lab1 pos docker vbox rm lab1 pos docker vbox ls EOF exit 0 } case "${1:-}" in -h|--help) usage ;; esac cmd="${1:-}" [ -z "$cmd" ] && usage container_exists() { docker container inspect "$1" &>/dev/null } container_running() { [[ "$(docker inspect -f '{{.State.Running}}' "$1" 2>/dev/null)" == "true" ]] } case "$cmd" in create) name="${2:-}" [ -z "$name" ] && usage # Parse remaining args: [image] [--dir ] image="ubuntu:22.04" custom_dir="" shift 2 || true while [ $# -gt 0 ]; do case "$1" in --dir) [ -z "${2:-}" ] && { echo "Missing value for --dir"; exit 1; } custom_dir="$2" shift 2 ;; *) image="$1" shift ;; esac done if container_exists "$name"; then echo "[!] Container already exists: $name" exit 0 fi if [ -n "$custom_dir" ]; then lab_dir="$(cd "$custom_dir" 2>/dev/null && pwd)" || { echo "[!] Directory not found: $custom_dir"; exit 1; } else lab_dir="$HOME/$name" fi mkdir -p "$lab_dir" echo "[+] Lab directory: $lab_dir" echo "[+] Pulling image: $image" docker pull "$image" echo "[+] Creating: $name" docker create \ -it \ --name "$name" \ --label linux_post_install.vbox=true \ -v "$lab_dir:$lab_dir" \ -w "$lab_dir" \ "$image" \ bash >/dev/null echo "[+] Done" if confirm "Enter now?"; then docker start "$name" >/dev/null exec docker exec -it -w "$lab_dir" "$name" bash fi ;; enter) name="${2:-}" [ -z "$name" ] && usage if ! container_exists "$name"; then echo "[!] Container not found: $name" exit 1 fi if ! container_running "$name"; then docker start "$name" >/dev/null fi # Detect working dir from container mounts lab_dir=$(docker inspect -f '{{range .Mounts}}{{if eq .Destination .Destination}}{{.Source}}{{end}}{{end}}' "$name" 2>/dev/null | head -1) if [ -n "$lab_dir" ] && [ -d "$lab_dir" ]; then exec docker exec -it -w "$lab_dir" "$name" bash else exec docker exec -it "$name" bash fi ;; start) name="${2:-}" [ -z "$name" ] && usage docker start "$name" ;; stop) name="${2:-}" [ -z "$name" ] && usage docker stop "$name" ;; rm) name="${2:-}" [ -z "$name" ] && usage docker rm -f "$name" ;; ls) docker ps -a --filter label=linux_post_install.vbox=true --format "table {{.Names}}\t{{.Image}}\t{{.Status}}" ;; *) usage ;; esac