#!/usr/bin/env bash set -euo pipefail # ────────────────────────────── # Config & helpers # ────────────────────────────── LOGFILE="${LOGFILE:-/var/log/docker-install.log}" : > "$LOGFILE" || { echo "Cannot write $LOGFILE (need root?)"; exit 1; } if [[ ${EUID:-$(id -u)} -ne 0 ]]; then SUDO="sudo"; else SUDO=""; fi TARGET_USER="${SUDO_USER:-$USER}" GREEN=$(tput setaf 2 || true); CYAN=$(tput setaf 6 || true); RESET=$(tput sgr0 || true) BOLD=$(tput bold || true); NORM=$(tput sgr0 || true) log() { echo -e "${CYAN}$*${RESET}" | tee -a "$LOGFILE"; } ok() { echo -e "${GREEN}$*${RESET}" | tee -a "$LOGFILE"; } run() { eval "$@" >>"$LOGFILE" 2>&1; } ascii=" ${CYAN} =++++ *#### -==== .****:-****.=***+ :####-=####.*#### : .====.:==== -==== -##= +***=.****:-****.=***+ ****= ####* ####*:####-=####.*#### ####+ *####*###*= ====-.====.:==== -==== ====: -########*. -+++++++++++++++++++++++++++++++**#####==-: =#####################################: :###################################*. *#################################= .*##############################+. +##########################*- .=*####################+-. .-=+**######**+=-:. ${RESET}" clear echo -e "$ascii" # ────────────────────────────── # Arguments # ────────────────────────────── ACTION="install" # install | uninstall PURGE_REPO="no" # yes | no for arg in "${@:-}"; do case "$arg" in --uninstall|-u) ACTION="uninstall" ;; --purge-repo) PURGE_REPO="yes" ;; --help|-h) cat <&2; exit 1; fi case "${ID:-}" in ubuntu) BASE_URL="https://download.docker.com/linux/ubuntu" ;; debian) BASE_URL="https://download.docker.com/linux/debian" ;; *) echo "Unsupported distribution: ${ID:-unknown}. (Ubuntu/Debian only)"; exit 1 ;; esac CODENAME="${VERSION_CODENAME:-}" if [[ -z "$CODENAME" ]] && command -v lsb_release >/dev/null 2>&1; then CODENAME="$(lsb_release -cs)"; fi if [[ -z "$CODENAME" ]]; then echo "Unable to determine codename (VERSION_CODENAME)." >&2; exit 1; fi ARCH="$(dpkg --print-architecture)" PRETTY="${PRETTY_NAME:-$ID}" LISTFILE="/etc/apt/sources.list.d/docker.list" KEYFILE="/etc/apt/keyrings/docker.asc" REPO_LINE="deb [arch=${ARCH} signed-by=${KEYFILE}] ${BASE_URL} ${CODENAME} stable" echo -e "Mode: ${CYAN}${BOLD}${ACTION^^}${RESET} | ${BOLD}${PRETTY}${RESET} (${BOLD}${CODENAME}${RESET}), arch=${CYAN}${ARCH}${RESET}" echo -e "Detailed logs: ${CYAN}${LOGFILE}${RESET}\n" # ────────────────────────────── # INSTALL Functions # ────────────────────────────── install_docker() { echo -e "${CYAN}1) Installing prerequisites (ca-certificates, curl, gnupg, acl)${RESET}" run "$SUDO apt-get update -y" run "$SUDO apt-get install -y ca-certificates curl gnupg acl" echo -e "${CYAN}2) Preparing Docker keyring${RESET}" run "$SUDO install -m 0755 -d /etc/apt/keyrings" if [[ ! -f "$KEYFILE" ]]; then run "$SUDO curl -fsSL ${BASE_URL}/gpg -o ${KEYFILE}" run "$SUDO chmod a+r ${KEYFILE}" fi echo -e "${CYAN}3) Adding Docker APT repository (stable)${RESET}" echo "$REPO_LINE" | $SUDO tee "$LISTFILE" >/dev/null run "$SUDO apt-get update -y" echo -e "${CYAN}4) Installing Docker Engine + Buildx + Compose${RESET}" run "$SUDO apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin" echo -e "${CYAN}5) Enabling Docker service${RESET}" run "$SUDO systemctl enable --now docker" echo -e "${CYAN}6) Managing docker group and adding user${RESET}" if ! getent group docker >/dev/null 2>&1; then run "$SUDO groupadd docker"; fi if ! id -nG "$TARGET_USER" | grep -qw docker; then run "$SUDO usermod -aG docker '$TARGET_USER'"; fi echo -e "${CYAN}7) Creating and setting permissions for /opt/docker${RESET}" run "$SUDO mkdir -p /opt/docker" run "$SUDO chown root:docker /opt/docker" run "$SUDO chmod 2770 /opt/docker" run "$SUDO setfacl -R -m g:docker:rwx /opt/docker" run "$SUDO setfacl -R -d -m g:docker:rwx /opt/docker" echo -e "${CYAN}8) Verifying installation (hello-world)${RESET}" run "$SUDO docker run --rm hello-world" echo ""; ok "✅ Docker installation and verification completed." echo -e "Log out and log back in (${BOLD}logout/login${NORM}) to use Docker without sudo." } # ────────────────────────────── # UNINSTALL Functions # ────────────────────────────── uninstall_docker() { echo -e "${CYAN}1) Stopping Docker service (if running)${RESET}" if $SUDO systemctl is-active --quiet docker; then run "$SUDO systemctl stop docker"; fi run "$SUDO systemctl disable docker || true" echo -e "${CYAN}2) Removing Docker packages${RESET}" PKGS="docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin docker-ce-rootless-extras docker-scan-plugin docker.io" run "$SUDO DEBIAN_FRONTEND=noninteractive apt-get purge -y $PKGS || true" echo -e "${CYAN}3) Cleaning up dependencies${RESET}" run "$SUDO apt-get autoremove -y --purge || true" if [[ "$PURGE_REPO" == "yes" ]]; then echo -e "${CYAN}4) Removing Docker APT repo and GPG key${RESET}" run "$SUDO rm -f '$LISTFILE' || true" run "$SUDO rm -f '$KEYFILE' || true" run "$SUDO apt-get update -y || true" STEP_NEXT=5 else STEP_NEXT=4 fi echo -e "${CYAN}${STEP_NEXT}) Keeping local data and /opt/docker (no deletion)${RESET}" echo -e "${CYAN} → /opt/docker, /var/lib/docker, and /var/lib/containerd are NOT touched.${RESET}" echo ""; ok "🧹 Docker uninstallation complete (packages removed, data kept)." echo -e "You can manually delete ${BOLD}/var/lib/docker${NORM} and ${BOLD}/var/lib/containerd${NORM} if you want a full cleanup." } # ────────────────────────────── # Main # ────────────────────────────── case "$ACTION" in install) install_docker ;; uninstall) uninstall_docker ;; esac