#!/usr/bin/env bash

set -euo pipefail

SUDO=()
CURRENT_USER="${USER:-$(id -un)}"

if [[ $EUID -ne 0 ]]; then
    if command -v sudo >/dev/null 2>&1; then
        SUDO=(sudo)
    else
        echo "Error: this script must be run as root or sudo must be installed." >&2
        exit 1
    fi
fi

CONFLICTING_PACKAGES=(
    docker.io
    docker-compose
    docker-doc
    docker-buildx
    podman-docker
    containerd
    runc
)

INSTALLED_PACKAGES=()

for package in "${CONFLICTING_PACKAGES[@]}"; do
    if dpkg-query -W -f='${Status}' "$package" 2>/dev/null | grep -q '^install ok installed$'; then
        INSTALLED_PACKAGES+=("$package")
    fi
done

if ((${#INSTALLED_PACKAGES[@]} > 0)); then
    echo "Removing conflicting packages: ${INSTALLED_PACKAGES[*]}"
    "${SUDO[@]}" apt-get remove -y "${INSTALLED_PACKAGES[@]}"
fi

"${SUDO[@]}" apt-get update
"${SUDO[@]}" apt-get install -y ca-certificates curl

"${SUDO[@]}" install -m 0755 -d /etc/apt/keyrings

"${SUDO[@]}" curl -fsSL \
    https://download.docker.com/linux/debian/gpg \
    -o /etc/apt/keyrings/docker.asc

"${SUDO[@]}" chmod a+r /etc/apt/keyrings/docker.asc

. /etc/os-release

ARCH="$(dpkg --print-architecture)"

cat <<EOF | "${SUDO[@]}" tee /etc/apt/sources.list.d/docker.sources >/dev/null
Types: deb
URIs: https://download.docker.com/linux/debian
Suites: ${VERSION_CODENAME}
Components: stable
Architectures: ${ARCH}
Signed-By: /etc/apt/keyrings/docker.asc
EOF

"${SUDO[@]}" apt-get update

"${SUDO[@]}" apt-get install -y \
    docker-ce \
    docker-ce-cli \
    containerd.io \
    docker-buildx-plugin \
    docker-compose-plugin

# Allow the invoking non-root user to use Docker without sudo.
if [[ $EUID -ne 0 ]]; then
    if ! id -nG "$CURRENT_USER" | grep -qw docker; then
        echo "Adding $CURRENT_USER to the docker group..."
        "${SUDO[@]}" usermod -aG docker "$CURRENT_USER"
        echo "Log out and back in for docker group membership to take effect."
    fi
fi

docker --version
docker compose version

Revision history

2 saved

Oct 1, 2026

  1. 18:51
  2. 18:48