#!/bin/sh set -e # Docker CE for Linux installation script (Rootless mode) # # See https://docs.docker.com/go/rootless/ for the # installation steps. # # This script is meant for quick & easy install via: # $ curl -fsSL https://get.docker.com/rootless -o get-docker.sh # $ sh get-docker.sh # # NOTE: Make sure to verify the contents of the script # you downloaded matches the contents of install.sh # located at https://github.com/docker/docker-install # before executing. # # Git commit from https://github.com/docker/docker-install when # the script was uploaded (Should only be modified by upload job): SCRIPT_COMMIT_SHA=3b2a83b # This script should be run with an unprivileged user and install/setup Docker under $HOME/bin/. # The channel to install from: # * test # * stable # * nightly (deprecated) DEFAULT_CHANNEL_VALUE="stable" if [ -z "$CHANNEL" ]; then CHANNEL=$DEFAULT_CHANNEL_VALUE fi # The latest release is currently hard-coded. STABLE_LATEST="25.0.2" TEST_LATEST="25.0.2" STATIC_RELEASE_URL= STATIC_RELEASE_ROOTLESS_URL= case "$CHANNEL" in "stable") echo "# Installing stable version ${STABLE_LATEST}" STATIC_RELEASE_URL="https://download.docker.com/linux/static/$CHANNEL/$(uname -m)/docker-${STABLE_LATEST}.tgz" STATIC_RELEASE_ROOTLESS_URL="https://download.docker.com/linux/static/$CHANNEL/$(uname -m)/docker-rootless-extras-${STABLE_LATEST}.tgz" ;; "test") echo "# Installing test version ${TEST_LATEST}" STATIC_RELEASE_URL="https://download.docker.com/linux/static/$CHANNEL/$(uname -m)/docker-${TEST_LATEST}.tgz" STATIC_RELEASE_ROOTLESS_URL="https://download.docker.com/linux/static/$CHANNEL/$(uname -m)/docker-rootless-extras-${TEST_LATEST}.tgz" ;; "nightly") >&2 echo "DEPRECATED: the nightly channel has been deprecated and is no longer supported by this script."; exit 1 ;; *) >&2 echo "Aborting because of unknown CHANNEL \"$CHANNEL\". Set \$CHANNEL to either \"stable\" or \"test\"."; exit 1 ;; esac init_vars() { BIN="${DOCKER_BIN:-$HOME/bin}" DAEMON=dockerd SYSTEMD= if systemctl --user daemon-reload >/dev/null 2>&1; then SYSTEMD=1 fi } checks() { # OS verification: Linux only, point osx/win to helpful locations case "$(uname)" in Linux) ;; *) >&2 echo "Rootless Docker cannot be installed on $(uname)"; exit 1 ;; esac # User verification: deny running as root (unless forced?) if [ "$(id -u)" = "0" ] && [ -z "$FORCE_ROOTLESS_INSTALL" ]; then >&2 echo "Refusing to install rootless Docker as the root user"; exit 1 fi # HOME verification if [ ! -d "$HOME" ]; then >&2 echo "Aborting because HOME directory $HOME does not exist"; exit 1 fi if [ -d "$BIN" ]; then if [ ! -w "$BIN" ]; then >&2 echo "Aborting because $BIN is not writable"; exit 1 fi else if [ ! -w "$HOME" ]; then >&2 echo "Aborting because HOME (\"$HOME\") is not writable"; exit 1 fi fi # Existing rootful docker verification if [ -w /var/run/docker.sock ] && [ -z "$FORCE_ROOTLESS_INSTALL" ]; then >&2 echo "Aborting because rootful Docker is running and accessible. Set FORCE_ROOTLESS_INSTALL=1 to ignore."; exit 1 fi # Validate XDG_RUNTIME_DIR if [ ! -w "$XDG_RUNTIME_DIR" ]; then if [ -n "$SYSTEMD" ]; then >&2 echo "Aborting because systemd was detected but XDG_RUNTIME_DIR (\"$XDG_RUNTIME_DIR\") does not exist or is not writable" >&2 echo "Hint: this could happen if you changed users with 'su' or 'sudo'. To work around this:" >&2 echo "- try again by first running with root privileges 'loginctl enable-linger ' where is the unprivileged user and export XDG_RUNTIME_DIR to the value of RuntimePath as shown by 'loginctl show-user '" >&2 echo "- or simply log back in as the desired unprivileged user (ssh works for remote machines)" exit 1 fi fi # Already installed verification (unless force?). Only having docker cli binary previously shouldn't fail the build. if [ -x "$BIN/$DAEMON" ]; then # If rootless installation is detected print out the modified PATH and DOCKER_HOST that needs to be set. echo "# Existing rootless Docker detected at $BIN/$DAEMON" echo echo "# To reinstall or upgrade rootless Docker, run the following commands and then rerun the installation script:" echo "systemctl --user stop docker" echo "rm -f $BIN/$DAEMON" echo echo "# Alternatively, install the docker-ce-rootless-extras RPM/deb package for ease of package management (requires root)." echo "# See https://docs.docker.com/go/rootless/ for details." exit 0 fi INSTRUCTIONS= # uidmap dependency check if ! command -v newuidmap >/dev/null 2>&1; then if command -v apt-get >/dev/null 2>&1; then INSTRUCTIONS="apt-get install -y uidmap" elif command -v dnf >/dev/null 2>&1; then INSTRUCTIONS="dnf install -y shadow-utils" elif command -v yum >/dev/null 2>&1; then INSTRUCTIONS="curl -o /etc/yum.repos.d/vbatts-shadow-utils-newxidmap-epel-7.repo https://copr.fedorainfracloud.org/coprs/vbatts/shadow-utils-newxidmap/repo/epel-7/vbatts-shadow-utils-newxidmap-epel-7.repo yum install -y shadow-utils46-newxidmap" else echo "newuidmap binary not found. Please install with a package manager." exit 1 fi fi # iptables dependency check if [ -z "$SKIP_IPTABLES" ] && ! command -v iptables >/dev/null 2>&1 && [ ! -f /sbin/iptables ] && [ ! -f /usr/sbin/iptables ]; then if command -v apt-get >/dev/null 2>&1; then INSTRUCTIONS="${INSTRUCTIONS} apt-get install -y iptables" elif command -v dnf >/dev/null 2>&1; then INSTRUCTIONS="${INSTRUCTIONS} dnf install -y iptables" else echo "iptables binary not found. Please install with a package manager." exit 1 fi fi # ip_tables module dependency check if [ -z "$SKIP_IPTABLES" ] && ! lsmod | grep ip_tables >/dev/null 2>&1 && ! grep -q ip_tables "/lib/modules/$(uname -r)/modules.builtin"; then INSTRUCTIONS="${INSTRUCTIONS} modprobe ip_tables" fi # debian requires setting unprivileged_userns_clone if [ -f /proc/sys/kernel/unprivileged_userns_clone ]; then if [ "1" != "$(cat /proc/sys/kernel/unprivileged_userns_clone)" ]; then INSTRUCTIONS="${INSTRUCTIONS} cat < /etc/sysctl.d/50-rootless.conf kernel.unprivileged_userns_clone = 1 EOT sysctl --system" fi fi # centos requires setting max_user_namespaces if [ -f /proc/sys/user/max_user_namespaces ]; then if [ "0" = "$(cat /proc/sys/user/max_user_namespaces)" ]; then INSTRUCTIONS="${INSTRUCTIONS} cat < /etc/sysctl.d/51-rootless.conf user.max_user_namespaces = 28633 EOT sysctl --system" fi fi if [ -n "$INSTRUCTIONS" ]; then echo "# Missing system requirements. Please run following commands to # install the requirements and run this installer again. # Alternatively iptables checks can be disabled with SKIP_IPTABLES=1" echo echo "cat </dev/null 2>&1; then >&2 echo "Could not find records for the current user $(id -un) from /etc/subuid . Please make sure valid subuid range is set there. For example: echo \"$(id -un):100000:65536\" >> /etc/subuid" exit 1 fi if ! grep "^$(id -un):\|^$(id -u):" /etc/subgid >/dev/null 2>&1; then >&2 echo "Could not find records for the current user $(id -un) from /etc/subgid . Please make sure valid subuid range is set there. For example: echo \"$(id -un):100000:65536\" >> /etc/subgid" exit 1 fi } exec_setuptool() { if [ -n "$FORCE_ROOTLESS_INSTALL" ]; then set -- "$@" --force fi if [ -n "$SKIP_IPTABLES" ]; then set -- "$@" --skip-iptables fi ( set -x PATH="$BIN:$PATH" "$BIN/dockerd-rootless-setuptool.sh" install "$@" ) } do_install() { echo "# Executing docker rootless install script, commit: $SCRIPT_COMMIT_SHA" init_vars checks tmp=$(mktemp -d) trap 'rm -rf "$tmp"' EXIT INT TERM # Download tarballs docker-* and docker-rootless-extras=* ( cd "$tmp" curl -L -o docker.tgz "$STATIC_RELEASE_URL" curl -L -o rootless.tgz "$STATIC_RELEASE_ROOTLESS_URL" ) # Extract under $HOME/bin/ ( mkdir -p "$BIN" cd "$BIN" tar zxf "$tmp/docker.tgz" --strip-components=1 tar zxf "$tmp/rootless.tgz" --strip-components=1 ) exec_setuptool "$@" } do_install "$@"