Created
          August 9, 2025 21:21 
        
      - 
      
 - 
        
Save nukhes/cf4a7315aefcd5726b82312ea50c707a to your computer and use it in GitHub Desktop.  
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
  | #!/bin/bash | |
| # install_docker_agnostic.sh | |
| # A comprehensive, agnostic bash script for Docker Engine installation and rootless configuration on Linux. | |
| set -e | |
| # --- Global Variables --- | |
| DISTRO_ID="" | |
| DISTRO_LIKE="" | |
| PACKAGE_MANAGER="" | |
| KERNEL_VERSION="" | |
| USER_CHOICE_NON_ROOT="" | |
| # --- Functions --- | |
| # Function to log messages with consistent formatting | |
| log_message() { | |
| echo ">>> $(date +'%Y-%m-%d %H:%M:%S') - $1" | |
| } | |
| # Function to check for sudo privileges | |
| check_sudo() { | |
| log_message "Checking for sudo privileges..." | |
| if! command -v sudo &> /dev/null; then | |
| log_message "Error: sudo is not installed. Please install sudo or run as root." | |
| exit 1 | |
| fi | |
| if! sudo -l &> /dev/null; then | |
| log_message "Error: Current user does not have sudo privileges. Please ensure your user is in the sudoers file." | |
| exit 1 | |
| fi | |
| log_message "Sudo privileges confirmed." [1, 2, 3] | |
| } | |
| # Function to check internet connectivity | |
| check_internet_connectivity() { | |
| log_message "Checking internet connectivity..." | |
| if! curl -sSf https://download.docker.com/linux/static/stable/ > /dev/null; then | |
| log_message "Error: No internet connectivity. Please check your network connection." | |
| exit 1 | |
| fi | |
| log_message "Internet connectivity confirmed." | |
| } | |
| # Function to check kernel version | |
| check_kernel_version() { | |
| log_message "Checking kernel version..." | |
| KERNEL_VERSION=$(uname -r) | |
| # Extract major and minor version for comparison | |
| MAJOR_KERNEL=$(echo "$KERNEL_VERSION" | cut -d'.' -f1) | |
| MINOR_KERNEL=$(echo "$KERNEL_VERSION" | cut -d'.' -f2) | |
| if (( MAJOR_KERNEL < 3 | | |
| | (MAJOR_KERNEL == 3 && MINOR_KERNEL < 10) )); then | |
| log_message "Warning: Docker Engine requires Linux kernel version 3.10 or higher. Your kernel is $KERNEL_VERSION. Installation may fail." [1, 4, 5, 6] | |
| read -p "Do you wish to continue anyway? (y/N): " continue_install | |
| if$ ]]; then | |
| log_message "Installation aborted due to low kernel version." | |
| exit 1 | |
| fi | |
| else | |
| log_message "Kernel version $KERNEL_VERSION meets Docker requirements." [1, 4, 5, 6] | |
| fi | |
| } | |
| # Function to check for existing Docker installation | |
| check_existing_docker() { | |
| log_message "Checking for existing Docker installation..." | |
| if command -v docker &> /dev/null; then | |
| log_message "Existing Docker installation detected: $(docker --version). This script will attempt to install/update Docker." [7] | |
| read -p "Do you want to proceed with installation/update? (y/N): " proceed_existing | |
| if$ ]]; then | |
| log_message "Installation aborted by user." | |
| exit 1 | |
| fi | |
| else | |
| log_message "No existing Docker installation found." | |
| fi | |
| } | |
| # Function to detect Linux distribution and package manager | |
| detect_distro_and_pm() { | |
| log_message "Detecting Linux distribution and package manager..." | |
| if [[ -f /etc/os-release ]]; then | |
| # Source /etc/os-release to get distribution information [8, 9, 10, 5, 11, 12, 13] | |
| . /etc/os-release | |
| DISTRO_ID=$ID | |
| DISTRO_LIKE=$ID_LIKE | |
| log_message "Detected OS: $NAME (ID: $DISTRO_ID, ID_LIKE: $DISTRO_LIKE)" [8] | |
| else | |
| log_message "Error: /etc/os-release not found. Cannot reliably detect distribution." | |
| exit 1 | |
| fi | |
| if command -v apt &> /dev/null; then | |
| PACKAGE_MANAGER="apt" | |
| elif command -v dnf &> /dev/null; then | |
| PACKAGE_MANAGER="dnf" | |
| elif command -v yum &> /dev/null; then | |
| PACKAGE_MANAGER="yum" # Fallback for older RHEL/CentOS [11] | |
| elif command -v pacman &> /dev/null; then | |
| PACKAGE_MANAGER="pacman" | |
| elif command -v zypper &> /dev/null; then | |
| PACKAGE_MANAGER="zypper" | |
| else | |
| log_message "Error: No supported package manager (apt, dnf, yum, pacman, zypper) found." [11] | |
| exit 1 | |
| fi | |
| log_message "Detected package manager: $PACKAGE_MANAGER." [11] | |
| } | |
| # Function to install Docker on Debian/Ubuntu (APT-based systems) | |
| install_docker_apt() { | |
| log_message "Installing Docker Engine on Debian/Ubuntu..." | |
| sudo apt update -y [1, 14] | |
| sudo apt install -y ca-certificates curl gnupg lsb-release [1, 14] | |
| log_message "Adding Docker's official GPG key..." | |
| sudo mkdir -p /etc/apt/keyrings | |
| curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg [1, 14] | |
| sudo chmod a+r /etc/apt/keyrings/docker.gpg | |
| log_message "Setting up the stable Docker repository..." | |
| echo \ | |
| "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ | |
| $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \ | |
| sudo tee /etc/apt/sources.list.d/docker.list > /dev/null [1, 14] | |
| log_message "Updating apt package index again and installing Docker packages..." | |
| sudo apt update -y [1, 14] | |
| sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin [1, 14] | |
| log_message "Docker Engine installation complete for Debian/Ubuntu." | |
| } | |
| # Function to install Docker on RHEL/CentOS/Fedora (DNF-based systems) | |
| install_docker_dnf() { | |
| log_message "Installing Docker Engine on RHEL/CentOS/Fedora..." | |
| log_message "Removing any conflicting unofficial Docker packages..." | |
| sudo dnf remove -y docker \ | |
| docker-client \ | |
| docker-client-latest \ | |
| docker-common \ | |
| docker-latest \ | |
| docker-latest-logrotate \ | |
| docker-logrotate \ | |
| docker-engine \ | |
| podman \ | |
| runc | | |
| | true # Continue if packages are not found [2, 15] | |
| log_message "Installing dnf-plugins-core and setting up Docker repository..." | |
| sudo dnf -y install dnf-plugins-core [2, 15, 16] | |
| sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo | | |
| | \ | |
| sudo dnf config-manager --add-repo https://download.docker.com/linux/fedora/docker-ce.repo | | |
| | \ | |
| sudo dnf config-manager --add-repo https://download.docker.com/linux/rhel/docker-ce.repo [2, 15, 16] | |
| log_message "Installing Docker Engine and its dependencies..." | |
| sudo dnf install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin [2, 15, 16] | |
| log_message "Docker Engine installation complete for RHEL/CentOS/Fedora." | |
| } | |
| # Function to install Docker on Arch Linux (Pacman-based systems) | |
| install_docker_pacman() { | |
| log_message "Installing Docker Engine on Arch Linux..." | |
| log_message "Updating pacman package database and installing Docker..." | |
| sudo pacman -Syu --noconfirm docker [17] | |
| log_message "Docker Engine installation complete for Arch Linux." | |
| } | |
| # Function for post-installation verification | |
| post_installation_verification() { | |
| log_message "Enabling and starting Docker service..." | |
| sudo systemctl enable --now docker [2, 15, 17, 16] | |
| log_message "Verifying Docker installation by running hello-world container..." | |
| sudo docker run hello-world [14, 2, 15, 3, 4, 17, 16] | |
| log_message "Docker installation verified successfully." | |
| } | |
| # Function to set up Docker Rootless mode | |
| setup_rootless_mode() { | |
| log_message "Setting up Docker in Rootless mode (Recommended for security)..." | |
| log_message "Installing Rootless mode prerequisites (requires sudo for system packages)..." | |
| case "$PACKAGE_MANAGER" in | |
| apt) | |
| sudo apt update -y | |
| sudo apt install -y uidmap dbus-user-session [1, 18] | |
| if]; then # Debian 11 specific [1, 18] | |
| sudo apt install -y fuse-overlayfs [1, 18] | |
| fi | |
| sudo apt install -y slirp4netns | | |
| | true # slirp4netns might be installed or not needed [1, 18] | |
| ;; | |
| dnf|yum) | |
| sudo dnf install -y newuidmap newgidmap dbus-daemon-tools | | |
| | sudo yum install -y newuidmap newgidmap dbus-daemon-tools | |
| sudo dnf install -y fuse-overlayfs slirp4netns | | |
| | sudo yum install -y fuse-overlayfs slirp4netns | | |
| | true | |
| ;; | |
| pacman) | |
| sudo pacman -Syu --noconfirm newuidmap newgidmap dbus fuse-overlayfs slirp4netns | | |
| | true | |
| ;; | |
| *) | |
| log_message "Warning: Automatic installation of Rootless prerequisites not supported for $PACKAGE_MANAGER. Please install 'newuidmap', 'newgidmap', 'dbus-user-session' (or equivalent), 'fuse-overlayfs' (if on Debian 11), and 'slirp4netns' manually." | |
| ;; | |
| esac | |
| log_message "Running dockerd-rootless-setuptool.sh install..." | |
| # Ensure dockerd-rootless-setuptool.sh is available, it's usually part of docker-ce-rootless-extras | |
| if! command -v dockerd-rootless-setuptool.sh &> /dev/null; then | |
| log_message "Error: dockerd-rootless-setuptool.sh not found. Please ensure 'docker-ce-rootless-extras' package is installed." | |
| log_message "For Debian/Ubuntu: sudo apt install -y docker-ce-rootless-extras" | |
| log_message "For RHEL/CentOS/Fedora: sudo dnf install -y docker-ce-rootless-extras" | |
| log_message "For Arch Linux: It's usually part of the 'docker' package or 'docker-git'." | |
| exit 1 | |
| fi | |
| dockerd-rootless-setuptool.sh install [1, 18] | |
| log_message "Enabling systemd lingering for current user ($USER) to auto-start rootless daemon on boot..." | |
| sudo loginctl enable-linger "$USER" [1, 18] | |
| log_message "Rootless mode setup complete. Please add the following to your shell profile (~/.bashrc, ~/.profile, etc.) and re-login or source it:" | |
| echo "export PATH=/usr/bin:$PATH" [1, 18] | |
| echo "export DOCKER_HOST=unix:///run/user/$(id -u)/docker.sock" [1, 18] | |
| log_message "You can now run 'docker run hello-world' without sudo." | |
| } | |
| # Function to add user to docker group | |
| setup_docker_group() { | |
| log_message "Setting up Docker for non-root access by adding user to 'docker' group (less secure than Rootless mode)." | |
| log_message "WARNING: Adding a user to the 'docker' group grants root-level privileges to that user. This is a significant security risk. Rootless mode is highly recommended instead." [1, 19, 20] | |
| if! grep -q "^docker:" /etc/group; then | |
| log_message "Creating 'docker' group..." | |
| sudo groupadd docker [1, 19, 20, 21] | |
| else | |
| log_message "'docker' group already exists." | |
| fi | |
| log_message "Adding current user ($USER) to the 'docker' group..." | |
| sudo usermod -aG docker "$USER" [1, 19, 7, 20, 21, 22] | |
| log_message "Group membership updated. For changes to take effect, you must either:" | |
| log_message "1. Log out and log back in." [1, 19, 7, 20, 21] | |
| log_message "2. Run 'newgrp docker' in your current terminal session (this will start a new shell)." [1, 19, 7, 20, 21] | |
| log_message "After re-logging in or running 'newgrp docker', verify with 'groups' command that 'docker' is listed." [16, 9, 23] | |
| log_message "Checking and fixing permissions for ~/.docker directory if necessary..." | |
| if [[ -d "$HOME/.docker" ]]; then | |
| sudo chown "$USER":"$USER" "$HOME/.docker" -R [1, 19] | |
| sudo chmod g+rwx "$HOME/.docker" -R [1, 19] | |
| log_message "Permissions for ~/.docker adjusted." | |
| fi | |
| log_message "You should now be able to run 'docker run hello-world' without sudo after re-logging in or using 'newgrp docker'." | |
| } | |
| # --- Main Script Execution --- | |
| log_message "Starting Docker Engine installation script." | |
| check_sudo | |
| check_internet_connectivity | |
| check_kernel_version | |
| check_existing_docker | |
| detect_distro_and_pm | |
| log_message "Proceeding with Docker Engine installation for $DISTRO_ID using $PACKAGE_MANAGER..." | |
| case "$PACKAGE_MANAGER" in | |
| apt) | |
| install_docker_apt | |
| ;; | |
| dnf|yum) | |
| install_docker_dnf | |
| ;; | |
| pacman) | |
| install_docker_pacman | |
| ;; | |
| *) | |
| log_message "Error: Unsupported distribution or package manager. Exiting." | |
| exit 1 | |
| ;; | |
| esac | |
| post_installation_verification | |
| log_message "Docker Engine is installed and running." | |
| # --- Non-Root Setup Choice --- | |
| echo "" | |
| log_message "Choose your preferred method for non-root Docker access:" | |
| echo "1. Rootless Mode (Recommended for security, daemon runs as non-root user)" | |
| echo "2. Add user to 'docker' group (Simpler, but grants root-equivalent privileges)" | |
| echo "3. Skip non-root setup (You will need to use 'sudo' for all Docker commands)" | |
| read -p "Enter your choice (1, 2, or 3): " USER_CHOICE_NON_ROOT | |
| case "$USER_CHOICE_NON_ROOT" in | |
| 1) | |
| setup_rootless_mode | |
| ;; | |
| 2) | |
| setup_docker_group | |
| ;; | |
| 3) | |
| log_message "Skipping non-root setup. You will need to use 'sudo' for all Docker commands." | |
| ;; | |
| *) | |
| log_message "Invalid choice. Skipping non-root setup. You will need to use 'sudo' for all Docker commands." | |
| ;; | |
| esac | |
| log_message "Docker Engine installation and configuration script finished." | |
| log_message "Please remember to re-login or open a new terminal session for group changes/environment variables to take effect." | 
  
    Sign up for free
    to join this conversation on GitHub.
    Already have an account?
    Sign in to comment