#!/usr/bin/env bash # shellcheck disable=SC2086 # Installs Docker Engine on Linux, or shows instructions for macOS/Windows. # Docker: https://www.docker.com/ # OrbStack (macOS alternative): https://orbstack.dev/ # # Supported platforms: # Linux (apt) : Ubuntu, Debian, and derivatives — Docker official apt repo # Linux (dnf) : RHEL, Fedora, CentOS Stream, Rocky, Alma — Docker official dnf repo # macOS : Not supported — shows instructions for OrbStack or Docker Desktop # Windows : Not supported — use install-docker.ps1 or Docker Desktop # # Prerequisites: # - Linux: curl, sudo # - macOS/Windows: follow the printed instructions set -euo pipefail # ──────────────────────────────────────────── # Constants # ──────────────────────────────────────────── DOCKER_GPG_URL="https://download.docker.com/linux/ubuntu/gpg" DOCKER_APT_REPO_URL="https://download.docker.com/linux/ubuntu" DOCKER_DNF_REPO_URL="https://download.docker.com/linux/rhel/docker-ce.repo" # ──────────────────────────────────────────── # Utility functions (all stderr output) # ──────────────────────────────────────────── info() { echo "[INFO] $*" >&2; } warn() { echo "[WARN] $*" >&2; } error() { echo "[ERROR] $*" >&2 exit 1 } success() { echo "[OK] $*" >&2; } # ──────────────────────────────────────────── # Detect OS # ──────────────────────────────────────────── OS="$(uname -s)" case "$OS" in Linux) ;; Darwin) info "macOS detected. Docker Engine is not installed via this script on macOS." info "" info "Please install one of the following:" info "" info " 1. OrbStack (recommended, lightweight):" info " https://orbstack.dev/" info "" info " 2. Docker Desktop for Mac:" info " https://www.docker.com/products/docker-desktop/" info "" exit 0 ;; *) info "Unsupported OS: $OS. This script only supports Linux." info "" info "For Windows, install one of the following:" info "" info " 1. Docker Desktop for Windows:" info " https://www.docker.com/products/docker-desktop/" info "" info " 2. WSL2 with Docker Engine:" info " Install WSL2, then run this script inside a WSL2 Linux distro." info "" exit 0 ;; esac ARCH="$(uname -m)" info "Platform: $OS ($ARCH)" # ──────────────────────────────────────────── # Check prerequisites # ──────────────────────────────────────────── command -v curl &>/dev/null || error "'curl' is required. Install it first." command -v sudo &>/dev/null || error "'sudo' is required." # ──────────────────────────────────────────── # Step 1: Check if Docker is already installed # ──────────────────────────────────────────── if command -v docker &>/dev/null; then CURRENT_VER="$(docker --version 2>/dev/null || echo 'unknown')" info "Docker is already installed ($CURRENT_VER). Skipping installation." info "To reinstall or upgrade, uninstall first: sudo apt remove docker-ce docker-ce-cli containerd.io" success "Docker is available: $(command -v docker)" exit 0 fi # ──────────────────────────────────────────── # Step 2: Install Docker Engine # ──────────────────────────────────────────── info "Installing Docker Engine..." if command -v apt-get &>/dev/null; then # ── apt-based systems (Ubuntu, Debian, etc.) ── info "Detected apt-based system. Using Docker official apt repository..." # Add Docker's official GPG key sudo apt-get update -y sudo apt-get install -y ca-certificates curl sudo install -m 0755 -d /etc/apt/keyrings sudo curl -fsSL "$DOCKER_GPG_URL" -o /etc/apt/keyrings/docker.asc sudo chmod a+r /etc/apt/keyrings/docker.asc # Add the repository to Apt sources CODENAME="$(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")" ARCH_DEB="$(dpkg --print-architecture)" sudo tee /etc/apt/sources.list.d/docker.sources >/dev/null </dev/null; then # ── dnf-based systems (RHEL, Fedora, CentOS Stream, Rocky, Alma) ── info "Detected dnf-based system. Using Docker official dnf repository..." sudo dnf config-manager --add-repo "$DOCKER_DNF_REPO_URL" sudo dnf -y install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin sudo systemctl --now enable docker success "Docker installed via dnf" else error "No supported package manager found (apt-get or dnf). Install Docker manually: https://docs.docker.com/engine/install/" fi # ──────────────────────────────────────────── # Step 3: Add current user to docker group # ──────────────────────────────────────────── info "Adding current user to the docker group..." sudo usermod -aG docker "$(whoami)" success "User '$(whoami)' added to the docker group" info "" info "NOTE: Group membership takes effect on next login." info " To apply immediately in this session, run: newgrp docker" info " Or log out and log back in." # ──────────────────────────────────────────── # Step 4: Verify installation # ──────────────────────────────────────────── if command -v docker &>/dev/null; then DOCKER_VER="$(docker --version 2>/dev/null || echo 'unknown')" success "Docker is available: $DOCKER_VER" else # May need a new shell for group changes warn "Docker was installed but 'docker' command not found in current PATH." warn "Please open a new terminal or run: newgrp docker" fi # ──────────────────────────────────────────── # Step 5: Post-install notes # ──────────────────────────────────────────── info "" info "==================================================" success "Docker installation complete!" info "==================================================" info "" info "Getting started:" info " docker run hello-world - Verify installation" info " docker ps - List running containers" info " docker compose up -d - Start services with Compose" info " docker build -t . - Build an image" info "" info "Post-install steps (optional):" info " https://docs.docker.com/engine/install/linux-post-install/" info "" info "Manage Docker as non-root:" info " You have been added to the 'docker' group." info " Log out and back in for this to take effect." info "" info "Container monitoring with ctop:" info " Install ctop to monitor containers: install-ctop.sh"