diff --git a/src/docker-in-docker/devcontainer-feature.json b/src/docker-in-docker/devcontainer-feature.json index fe705db37..ecf22a0a3 100644 --- a/src/docker-in-docker/devcontainer-feature.json +++ b/src/docker-in-docker/devcontainer-feature.json @@ -1,6 +1,6 @@ { "id": "docker-in-docker", - "version": "2.12.2", + "version": "2.12.3", "name": "Docker (Docker-in-Docker)", "documentationURL": "https://github.com/devcontainers/features/tree/main/src/docker-in-docker", "description": "Create child containers *inside* a container, independent from the host's docker instance. Installs Docker extension in the container along with needed CLIs.", diff --git a/src/docker-in-docker/install.sh b/src/docker-in-docker/install.sh index b43a12918..6b1c817c6 100755 --- a/src/docker-in-docker/install.sh +++ b/src/docker-in-docker/install.sh @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!//usr/bin/env bash #------------------------------------------------------------------------------------------------------------- # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information. @@ -6,8 +6,10 @@ # # Docs: https://github.com/microsoft/vscode-dev-containers/blob/main/script-library/docs/docker-in-docker.md # Maintainer: The Dev Container spec maintainers - - +if [ -z "$BASH_VERSION" ]; then +echo "❌ This script must be run with bash, not sh." +exit 1 +fi DOCKER_VERSION="${VERSION:-"latest"}" # The Docker/Moby Engine + CLI should match in version USE_MOBY="${MOBY:-"true"}" MOBY_BUILDX_VERSION="${MOBYBUILDXVERSION:-"latest"}" @@ -23,19 +25,19 @@ DOCKER_LICENSED_ARCHIVE_VERSION_CODENAMES="bookworm buster bullseye bionic focal DISABLE_IP6_TABLES="${DISABLEIP6TABLES:-false}" # Default: Exit on any failure. -set -e +set -ex # Clean up rm -rf /var/lib/apt/lists/* # Setup STDERR. err() { - echo "(!) $*" >&2 +echo "(!) $*" >&2 } if [ "$(id -u)" -ne 0 ]; then - err 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.' - exit 1 +err 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.' +exit 1 fi ################### @@ -45,140 +47,171 @@ fi # Determine the appropriate non-root user if [ "${USERNAME}" = "auto" ] || [ "${USERNAME}" = "automatic" ]; then - USERNAME="" - POSSIBLE_USERS=("vscode" "node" "codespace" "$(awk -v val=1000 -F ":" '$3==val{print $1}' /etc/passwd)") - for CURRENT_USER in "${POSSIBLE_USERS[@]}"; do - if id -u ${CURRENT_USER} > /dev/null 2>&1; then - USERNAME=${CURRENT_USER} - break - fi - done - if [ "${USERNAME}" = "" ]; then - USERNAME=root - fi +USERNAME="" +POSSIBLE_USERS=("vscode" "node" "codespace" "$(awk -v val=1000 -F ":" '$3==val{print $1}' /etc/passwd)") +for CURRENT_USER in "${POSSIBLE_USERS[@]}"; do +if id -u ${CURRENT_USER} > /dev/null 2>&1; then +USERNAME=${CURRENT_USER} +break +fi +done +if [ "${USERNAME}" = "" ]; then +USERNAME=root +fi elif [ "${USERNAME}" = "none" ] || ! id -u ${USERNAME} > /dev/null 2>&1; then - USERNAME=root +USERNAME=root fi apt_get_update() { - if [ "$(find /var/lib/apt/lists/* | wc -l)" = "0" ]; then - echo "Running apt-get update..." - apt-get update -y - fi +. /etc/os-release +if [ "$ID" = "ubuntu" ] || [ "$ID" = "debian" ]; then +if [ "$(find /var/lib/apt/lists/* | wc -l)" = "0" ]; then +echo "Running apt-get update..." +apt-get update -y +fi +fi } # Checks if packages are installed and installs them if not check_packages() { - if ! dpkg -s "$@" > /dev/null 2>&1; then - apt_get_update - apt-get -y install --no-install-recommends "$@" - fi + +if [ "$ID" = "ubuntu" ] || [ "$ID" = "debian" ] || [ "$ID_LIKE" = "debian" ]; then +if ! dpkg -s "$@" > /dev/null 2>&1; then +apt_get_update +apt-get -y install --no-install-recommends "$@" +fi +elif [ "$ID" = "fedora" ] || [ "$ID" = "centos" ] || [ "$ID_LIKE" == "rhel" ]; then +if ! dnf list installed "$@" > /dev/null 2>&1; then +dnf -y install "$@" +fi +fi + +} +missing=0 +for cmd in git wget which; do +command -v $cmd &>/dev/null || { +echo "$cmd not found" +missing=1 } +done + +if [ $missing -eq 1 ]; then +echo "Installing missing packages..." +if command -v dnf &>/dev/null; then +dnf install -y git wget which curl jq +elif command -v apt &>/dev/null; then +apt-get update && apt-get install -y git wget curl jq +else +echo "Unsupported package manager" +exit 1 +fi +fi + # Figure out correct version of a three part version number is not passed find_version_from_git_tags() { - local variable_name=$1 - local requested_version=${!variable_name} - if [ "${requested_version}" = "none" ]; then return; fi - local repository=$2 - local prefix=${3:-"tags/v"} - local separator=${4:-"."} - local last_part_optional=${5:-"false"} - if [ "$(echo "${requested_version}" | grep -o "." | wc -l)" != "2" ]; then - local escaped_separator=${separator//./\\.} - local last_part - if [ "${last_part_optional}" = "true" ]; then - last_part="(${escaped_separator}[0-9]+)?" - else - last_part="${escaped_separator}[0-9]+" - fi - local regex="${prefix}\\K[0-9]+${escaped_separator}[0-9]+${last_part}$" - local version_list="$(git ls-remote --tags ${repository} | grep -oP "${regex}" | tr -d ' ' | tr "${separator}" "." | sort -rV)" - if [ "${requested_version}" = "latest" ] || [ "${requested_version}" = "current" ] || [ "${requested_version}" = "lts" ]; then - declare -g ${variable_name}="$(echo "${version_list}" | head -n 1)" - else - set +e - declare -g ${variable_name}="$(echo "${version_list}" | grep -E -m 1 "^${requested_version//./\\.}([\\.\\s]|$)")" - set -e - fi - fi - if [ -z "${!variable_name}" ] || ! echo "${version_list}" | grep "^${!variable_name//./\\.}$" > /dev/null 2>&1; then - err "Invalid ${variable_name} value: ${requested_version}\nValid values:\n${version_list}" >&2 - exit 1 - fi - echo "${variable_name}=${!variable_name}" +local variable_name=$1 +local requested_version=${!variable_name} +if [ "${requested_version}" = "none" ]; then return; fi +local repository=$2 +local prefix=${3:-"tags/v"} +local separator=${4:-"."} +local last_part_optional=${5:-"false"} +if [ "$(echo "${requested_version}" | grep -o "." | wc -l)" != "2" ]; then +local escaped_separator=${separator//./\\.} +local last_part +if [ "${last_part_optional}" = "true" ]; then +last_part="(${escaped_separator}[0-9]+)?" +else +last_part="${escaped_separator}[0-9]+" +fi +local regex="${prefix}\\K[0-9]+${escaped_separator}[0-9]+${last_part}$" +local version_list="$(git ls-remote --tags ${repository} | grep -oP "${regex}" | tr -d ' ' | tr "${separator}" "." | sort -rV)" +if [ "${requested_version}" = "latest" ] || [ "${requested_version}" = "current" ] || [ "${requested_version}" = "lts" ]; then +declare -g ${variable_name}="$(echo "${version_list}" | head -n 1)" +else +set +e +declare -g ${variable_name}="$(echo "${version_list}" | grep -E -m 1 "^${requested_version//./\\.}([\\.\\s]|$)")" +set -e +fi +fi +if [ -z "${!variable_name}" ] || ! echo "${version_list}" | grep "^${!variable_name//./\\.}$" > /dev/null 2>&1; then +err "Invalid ${variable_name} value: ${requested_version}\nValid values:\n${version_list}" >&2 +exit 1 +fi +echo "${variable_name}=${!variable_name}" } # Use semver logic to decrement a version number then look for the closest match find_prev_version_from_git_tags() { - local variable_name=$1 - local current_version=${!variable_name} - local repository=$2 - # Normally a "v" is used before the version number, but support alternate cases - local prefix=${3:-"tags/v"} - # Some repositories use "_" instead of "." for version number part separation, support that - local separator=${4:-"."} - # Some tools release versions that omit the last digit (e.g. go) - local last_part_optional=${5:-"false"} - # Some repositories may have tags that include a suffix (e.g. actions/node-versions) - local version_suffix_regex=$6 - # Try one break fix version number less if we get a failure. Use "set +e" since "set -e" can cause failures in valid scenarios. - set +e - major="$(echo "${current_version}" | grep -oE '^[0-9]+' || echo '')" - minor="$(echo "${current_version}" | grep -oP '^[0-9]+\.\K[0-9]+' || echo '')" - breakfix="$(echo "${current_version}" | grep -oP '^[0-9]+\.[0-9]+\.\K[0-9]+' 2>/dev/null || echo '')" - - if [ "${minor}" = "0" ] && [ "${breakfix}" = "0" ]; then - ((major=major-1)) - declare -g ${variable_name}="${major}" - # Look for latest version from previous major release - find_version_from_git_tags "${variable_name}" "${repository}" "${prefix}" "${separator}" "${last_part_optional}" - # Handle situations like Go's odd version pattern where "0" releases omit the last part - elif [ "${breakfix}" = "" ] || [ "${breakfix}" = "0" ]; then - ((minor=minor-1)) - declare -g ${variable_name}="${major}.${minor}" - # Look for latest version from previous minor release - find_version_from_git_tags "${variable_name}" "${repository}" "${prefix}" "${separator}" "${last_part_optional}" - else - ((breakfix=breakfix-1)) - if [ "${breakfix}" = "0" ] && [ "${last_part_optional}" = "true" ]; then - declare -g ${variable_name}="${major}.${minor}" - else - declare -g ${variable_name}="${major}.${minor}.${breakfix}" - fi - fi - set -e +local variable_name=$1 +local current_version=${!variable_name} +local repository=$2 +# Normally a "v" is used before the version number, but support alternate cases +local prefix=${3:-"tags/v"} +# Some repositories use "_" instead of "." for version number part separation, support that +local separator=${4:-"."} +# Some tools release versions that omit the last digit (e.g. go) +local last_part_optional=${5:-"false"} +# Some repositories may have tags that include a suffix (e.g. actions/node-versions) +local version_suffix_regex=$6 +# Try one break fix version number less if we get a failure. Use "set +e" since "set -e" can cause failures in valid scenarios. +set +e +major="$(echo "${current_version}" | grep -oE '^[0-9]+' || echo '')" +minor="$(echo "${current_version}" | grep -oP '^[0-9]+\.\K[0-9]+' || echo '')" +breakfix="$(echo "${current_version}" | grep -oP '^[0-9]+\.[0-9]+\.\K[0-9]+' 2>/dev/null || echo '')" + +if [ "${minor}" = "0" ] && [ "${breakfix}" = "0" ]; then +((major=major-1)) +declare -g ${variable_name}="${major}" +# Look for latest version from previous major release +find_version_from_git_tags "${variable_name}" "${repository}" "${prefix}" "${separator}" "${last_part_optional}" +# Handle situations like Go's odd version pattern where "0" releases omit the last part +elif [ "${breakfix}" = "" ] || [ "${breakfix}" = "0" ]; then +((minor=minor-1)) +declare -g ${variable_name}="${major}.${minor}" +# Look for latest version from previous minor release +find_version_from_git_tags "${variable_name}" "${repository}" "${prefix}" "${separator}" "${last_part_optional}" +else +((breakfix=breakfix-1)) +if [ "${breakfix}" = "0" ] && [ "${last_part_optional}" = "true" ]; then +declare -g ${variable_name}="${major}.${minor}" +else +declare -g ${variable_name}="${major}.${minor}.${breakfix}" +fi +fi +set -e } # Function to fetch the version released prior to the latest version get_previous_version() { - local url=$1 - local repo_url=$2 - local variable_name=$3 - prev_version=${!variable_name} - - output=$(curl -s "$repo_url"); - if echo "$output" | jq -e 'type == "object"' > /dev/null; then - message=$(echo "$output" | jq -r '.message') - - if [[ $message == "API rate limit exceeded"* ]]; then - echo -e "\nAn attempt to find latest version using GitHub Api Failed... \nReason: ${message}" - echo -e "\nAttempting to find latest version using GitHub tags." - find_prev_version_from_git_tags prev_version "$url" "tags/v" - declare -g ${variable_name}="${prev_version}" - fi - elif echo "$output" | jq -e 'type == "array"' > /dev/null; then - echo -e "\nAttempting to find latest version using GitHub Api." - version=$(echo "$output" | jq -r '.[1].tag_name') - declare -g ${variable_name}="${version#v}" - fi - echo "${variable_name}=${!variable_name}" +local url=$1 +local repo_url=$2 +local variable_name=$3 +prev_version=${!variable_name} + +output=$(curl -s "$repo_url"); +if echo "$output" | jq -e 'type == "object"' > /dev/null; then +message=$(echo "$output" | jq -r '.message') + +if [[ $message == "API rate limit exceeded"* ]]; then +echo -e "\nAn attempt to find latest version using GitHub Api Failed... \nReason: ${message}" +echo -e "\nAttempting to find latest version using GitHub tags." +find_prev_version_from_git_tags prev_version "$url" "tags/v" +declare -g ${variable_name}="${prev_version}" +fi +elif echo "$output" | jq -e 'type == "array"' > /dev/null; then +echo -e "\nAttempting to find latest version using GitHub Api." +version=$(echo "$output" | jq -r '.[1].tag_name') +declare -g ${variable_name}="${version#v}" +fi +echo "${variable_name}=${!variable_name}" } get_github_api_repo_url() { - local url=$1 - echo "${url/https:\/\/github.com/https:\/\/api.github.com\/repos}/releases" +local url=$1 +echo "${url/https:\/\/github.com/https:\/\/api.github.com\/repos}/releases" } ########################################### @@ -191,299 +224,421 @@ export DEBIAN_FRONTEND=noninteractive # Source /etc/os-release to get OS info . /etc/os-release -# Fetch host/container arch. +# Fetch host/container architecture +if [ "$ID" = "ubuntu" ] || [ "$ID" = "debian" ]; then architecture="$(dpkg --print-architecture)" +elif [ "$ID" = "fedora" ] || [ "$ID_LIKE" = "rhel" ]; then +architecture="$(uname -m)" +case "$architecture" in +x86_64) architecture="amd64" ;; +aarch64) architecture="arm64" ;; +*) echo "Unsupported architecture: $architecture"; exit 1 ;; +esac +else +echo "Unsupported operating system: $ID" +exit 1 +fi + # Check if distro is supported if [ "${USE_MOBY}" = "true" ]; then - if [[ "${DOCKER_MOBY_ARCHIVE_VERSION_CODENAMES}" != *"${VERSION_CODENAME}"* ]]; then - err "Unsupported distribution version '${VERSION_CODENAME}'. To resolve, either: (1) set feature option '\"moby\": false' , or (2) choose a compatible OS distribution" - err "Support distributions include: ${DOCKER_MOBY_ARCHIVE_VERSION_CODENAMES}" - exit 1 - fi - echo "Distro codename '${VERSION_CODENAME}' matched filter '${DOCKER_MOBY_ARCHIVE_VERSION_CODENAMES}'" +if [[ "${DOCKER_MOBY_ARCHIVE_VERSION_CODENAMES}" != *"${VERSION_CODENAME}"* ]]; then +err "Unsupported distribution version '${VERSION_CODENAME}'. To resolve, either: (1) set feature option '\"moby\": false' , or (2) choose a compatible OS distribution" +err "Support distributions include: ${DOCKER_MOBY_ARCHIVE_VERSION_CODENAMES}" +exit 1 +fi +echo "Distro codename '${VERSION_CODENAME}' matched filter '${DOCKER_MOBY_ARCHIVE_VERSION_CODENAMES}'" else - if [[ "${DOCKER_LICENSED_ARCHIVE_VERSION_CODENAMES}" != *"${VERSION_CODENAME}"* ]]; then - err "Unsupported distribution version '${VERSION_CODENAME}'. To resolve, please choose a compatible OS distribution" - err "Support distributions include: ${DOCKER_LICENSED_ARCHIVE_VERSION_CODENAMES}" - exit 1 - fi - echo "Distro codename '${VERSION_CODENAME}' matched filter '${DOCKER_LICENSED_ARCHIVE_VERSION_CODENAMES}'" +if [[ "${DOCKER_LICENSED_ARCHIVE_VERSION_CODENAMES}" != *"${VERSION_CODENAME}"* ]]; then +err "Unsupported distribution version '${VERSION_CODENAME}'. To resolve, please choose a compatible OS distribution" +err "Support distributions include: '${DOCKER_LICENSED_ARCHIVE_VERSION_CODENAMES}'" +exit 1 +fi +echo "Distro codename '${VERSION_CODENAME}' matched filter '${DOCKER_LICENSED_ARCHIVE_VERSION_CODENAMES}'" fi # Install dependencies check_packages apt-transport-https curl ca-certificates pigz iptables gnupg2 dirmngr wget jq if ! type git > /dev/null 2>&1; then - check_packages git +check_packages git fi - # Swap to legacy iptables for compatibility if type iptables-legacy > /dev/null 2>&1; then - update-alternatives --set iptables /usr/sbin/iptables-legacy - update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy +update-alternatives --set iptables /usr/sbin/iptables-legacy +update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy +fi +# https://github.com/devcontainers/features/issues/1235 +if uname -r | grep -q '\.fc'; then +sudo update-alternatives --set iptables /usr/sbin/iptables-nft fi - - # Set up the necessary apt repos (either Microsoft's or Docker's) +if [ "$ID" = "ubuntu" ] || [ "$ID" = "debian" ]; then if [ "${USE_MOBY}" = "true" ]; then - # Name of open source engine/cli - engine_package_name="moby-engine" - cli_package_name="moby-cli" +# Name of open source engine/cli +engine_package_name="moby-engine" +cli_package_name="moby-cli" - # Import key safely and import Microsoft apt repo - curl -sSL ${MICROSOFT_GPG_KEYS_URI} | gpg --dearmor > /usr/share/keyrings/microsoft-archive-keyring.gpg - echo "deb [arch=${architecture} signed-by=/usr/share/keyrings/microsoft-archive-keyring.gpg] https://packages.microsoft.com/repos/microsoft-${ID}-${VERSION_CODENAME}-prod ${VERSION_CODENAME} main" > /etc/apt/sources.list.d/microsoft.list +# Import key safely and import Microsoft apt repo +curl -sSL ${MICROSOFT_GPG_KEYS_URI} | gpg --dearmor > /usr/share/keyrings/microsoft-archive-keyring.gpg +echo "deb [arch=${architecture} signed-by=/usr/share/keyrings/microsoft-archive-keyring.gpg] https://packages.microsoft.com/repos/microsoft-${ID}-${VERSION_CODENAME}-prod ${VERSION_CODENAME} main" > /etc/apt/sources.list.d/microsoft.list else - # Name of licensed engine/cli - engine_package_name="docker-ce" - cli_package_name="docker-ce-cli" +# Name of licensed engine/cli +engine_package_name="docker-ce" +cli_package_name="docker-ce-cli" - # Import key safely and import Docker apt repo - curl -fsSL https://download.docker.com/linux/${ID}/gpg | gpg --dearmor > /usr/share/keyrings/docker-archive-keyring.gpg - echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/${ID} ${VERSION_CODENAME} stable" > /etc/apt/sources.list.d/docker.list +# Import key safely and import Docker apt repo +curl -fsSL https://download.docker.com/linux/${ID}/gpg | gpg --dearmor > /usr/share/keyrings/docker-archive-keyring.gpg +echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/${ID} ${VERSION_CODENAME} stable" > /etc/apt/sources.list.d/docker.list fi # Refresh apt lists apt-get update - +fi # Soft version matching if [ "${DOCKER_VERSION}" = "latest" ] || [ "${DOCKER_VERSION}" = "lts" ] || [ "${DOCKER_VERSION}" = "stable" ]; then - # Empty, meaning grab whatever "latest" is in apt repo - engine_version_suffix="" - cli_version_suffix="" +# Empty, meaning grab whatever "latest" is in apt repo +engine_version_suffix="" +cli_version_suffix="" else - # Fetch a valid version from the apt-cache (eg: the Microsoft repo appends +azure, breakfix, etc...) - docker_version_dot_escaped="${DOCKER_VERSION//./\\.}" - docker_version_dot_plus_escaped="${docker_version_dot_escaped//+/\\+}" - # Regex needs to handle debian package version number format: https://www.systutorials.com/docs/linux/man/5-deb-version/ - docker_version_regex="^(.+:)?${docker_version_dot_plus_escaped}([\\.\\+ ~:-]|$)" - set +e # Don't exit if finding version fails - will handle gracefully - cli_version_suffix="=$(apt-cache madison ${cli_package_name} | awk -F"|" '{print $2}' | sed -e 's/^[ \t]*//' | grep -E -m 1 "${docker_version_regex}")" - engine_version_suffix="=$(apt-cache madison ${engine_package_name} | awk -F"|" '{print $2}' | sed -e 's/^[ \t]*//' | grep -E -m 1 "${docker_version_regex}")" - set -e - if [ -z "${engine_version_suffix}" ] || [ "${engine_version_suffix}" = "=" ] || [ -z "${cli_version_suffix}" ] || [ "${cli_version_suffix}" = "=" ] ; then - err "No full or partial Docker / Moby version match found for \"${DOCKER_VERSION}\" on OS ${ID} ${VERSION_CODENAME} (${architecture}). Available versions:" - apt-cache madison ${cli_package_name} | awk -F"|" '{print $2}' | grep -oP '^(.+:)?\K.+' - exit 1 - fi - echo "engine_version_suffix ${engine_version_suffix}" - echo "cli_version_suffix ${cli_version_suffix}" +# Fetch a valid version from the apt-cache (eg: the Microsoft repo appends +azure, breakfix, etc...) +docker_version_dot_escaped="${DOCKER_VERSION//./\\.}" +docker_version_dot_plus_escaped="${docker_version_dot_escaped//+/\\+}" +# Regex needs to handle debian package version number format: https://www.systutorials.com/docs/linux/man/5-deb-version/ +docker_version_regex="^(.+:)?${docker_version_dot_plus_escaped}([\\.\\+ ~:-]|$)" +set +e # Don't exit if finding version fails - will handle gracefully +cli_version_suffix="=$(apt-cache madison ${cli_package_name} | awk -F"|" '{print $2}' | sed -e 's/^[ \t]*//' | grep -E -m 1 "${docker_version_regex}")" +engine_version_suffix="=$(apt-cache madison ${engine_package_name} | awk -F"|" '{print $2}' | sed -e 's/^[ \t]*//' | grep -E -m 1 "${docker_version_regex}")" +set -e +if [ -z "${engine_version_suffix}" ] || [ "${engine_version_suffix}" = "=" ] || [ -z "${cli_version_suffix}" ] || [ "${cli_version_suffix}" = "=" ] ; then +err "No full or partial Docker / Moby version match found for \"${DOCKER_VERSION}\" on OS ${ID} ${VERSION_CODENAME} (${architecture}). Available versions:" +apt-cache madison ${cli_package_name} | awk -F"|" '{print $2}' | grep -oP '^(.+:)?\K.+' +exit 1 +fi +echo "engine_version_suffix ${engine_version_suffix}" +echo "cli_version_suffix ${cli_version_suffix}" fi # Version matching for moby-buildx if [ "${USE_MOBY}" = "true" ]; then - if [ "${MOBY_BUILDX_VERSION}" = "latest" ]; then - # Empty, meaning grab whatever "latest" is in apt repo - buildx_version_suffix="" - else - buildx_version_dot_escaped="${MOBY_BUILDX_VERSION//./\\.}" - buildx_version_dot_plus_escaped="${buildx_version_dot_escaped//+/\\+}" - buildx_version_regex="^(.+:)?${buildx_version_dot_plus_escaped}([\\.\\+ ~:-]|$)" - set +e - buildx_version_suffix="=$(apt-cache madison moby-buildx | awk -F"|" '{print $2}' | sed -e 's/^[ \t]*//' | grep -E -m 1 "${buildx_version_regex}")" - set -e - if [ -z "${buildx_version_suffix}" ] || [ "${buildx_version_suffix}" = "=" ]; then - err "No full or partial moby-buildx version match found for \"${MOBY_BUILDX_VERSION}\" on OS ${ID} ${VERSION_CODENAME} (${architecture}). Available versions:" - apt-cache madison moby-buildx | awk -F"|" '{print $2}' | grep -oP '^(.+:)?\K.+' - exit 1 - fi - echo "buildx_version_suffix ${buildx_version_suffix}" - fi +if [ "${MOBY_BUILDX_VERSION}" = "latest" ]; then +# Empty, meaning grab whatever "latest" is in apt repo +buildx_version_suffix="" +else +buildx_version_dot_escaped="${MOBY_BUILDX_VERSION//./\\.}" +buildx_version_dot_plus_escaped="${buildx_version_dot_escaped//+/\\+}" +buildx_version_regex="^(.+:)?${buildx_version_dot_plus_escaped}([\\.\\+ ~:-]|$)" +set +e +buildx_version_suffix="=$(apt-cache madison moby-buildx | awk -F"|" '{print $2}' | sed -e 's/^[ \t]*//' | grep -E -m 1 "${buildx_version_regex}")" +set -e +if [ -z "${buildx_version_suffix}" ] || [ "${buildx_version_suffix}" = "=" ]; then +err "No full or partial moby-buildx version match found for \"${MOBY_BUILDX_VERSION}\" on OS ${ID} ${VERSION_CODENAME} (${architecture}). Available versions:" +apt-cache madison moby-buildx | awk -F"|" '{print $2}' | grep -oP '^(.+:)?\K.+' +exit 1 +fi +echo "buildx_version_suffix ${buildx_version_suffix}" +fi +fi + +install_docker_or_moby() { +# Check for the OS type +if [ -f /etc/os-release ]; then +. /etc/os-release fi -# Install Docker / Moby CLI if not already installed +# Set Fedora version for repository URL +RELEASE_VER=$(sed 's/\..*//' /etc/fedora-release) + +# Check if the user wants to use Moby (open-source version of Docker) +echo "Setting up Moby repository for Fedora..." +# Add Moby repository (Microsoft) +echo "[microsoft]" > /etc/yum.repos.d/microsoft.repo +echo "name=Microsoft Packages" >> /etc/yum.repos.d/microsoft.repo +echo "baseurl=https://packages.microsoft.com/yumrepos/microsoft-fedora$RELEASE_VER" >> /etc/yum.repos.d/microsoft.repo +echo "enabled=1" >> /etc/yum.repos.d/microsoft.repo +echo "gpgcheck=1" >> /etc/yum.repos.d/microsoft.repo +echo "gpgkey=https://packages.microsoft.com/keys/microsoft.asc" >> /etc/yum.repos.d/microsoft.repo + +# Install Moby Engine and CLI +echo "Installing Moby packages..." +sudo dnf install -y moby-engine moby-cli moby-buildx --skip-unavailable +# Final message +echo "Docker/Moby installation completed successfully!" +echo "Please log out and log back in to apply group changes." +} + if type docker > /dev/null 2>&1 && type dockerd > /dev/null 2>&1; then echo "Docker / Moby CLI and Engine already installed." -else - if [ "${USE_MOBY}" = "true" ]; then - # Install engine - set +e # Handle error gracefully - apt-get -y install --no-install-recommends moby-cli${cli_version_suffix} moby-buildx${buildx_version_suffix} moby-engine${engine_version_suffix} + elif [ "${USE_MOBY}" = "true" ] && { [ "$ID" = "ubuntu" ] || [ "$ID" = "debian" ]; }; then + # Install engine + set +e # Handle error gracefully + apt-get -y install --no-install-recommends \ + moby-cli${cli_version_suffix} \ + moby-buildx${buildx_version_suffix} \ + moby-engine${engine_version_suffix} exit_code=$? - set -e - + set -e + if [ ${exit_code} -ne 0 ]; then - err "Packages for moby not available in OS ${ID} ${VERSION_CODENAME} (${architecture}). To resolve, either: (1) set feature option '\"moby\": false' , or (2) choose a compatible OS version (eg: 'ubuntu-20.04')." - exit 1 + err "Packages for moby not available in OS ${ID} ${VERSION_CODENAME} (${architecture}). To resolve, either: (1) set feature option '\"moby\": false' , or (2) choose a compatible OS version (e.g., 'ubuntu-20.04')." + exit 1 fi - # Install compose - apt-get -y install --no-install-recommends moby-compose || err "Package moby-compose (Docker Compose v2) not available for OS ${ID} ${VERSION_CODENAME} (${architecture}). Skipping." - else - apt-get -y install --no-install-recommends docker-ce-cli${cli_version_suffix} docker-ce${engine_version_suffix} - # Install compose - apt-mark hold docker-ce docker-ce-cli - apt-get -y install --no-install-recommends docker-compose-plugin || echo "(*) Package docker-compose-plugin (Docker Compose v2) not available for OS ${ID} ${VERSION_CODENAME} (${architecture}). Skipping." + # Install compose + apt-get -y install --no-install-recommends moby-compose || \ + err "Package moby-compose (Docker Compose v2) not available for OS ${ID} ${VERSION_CODENAME} (${architecture}). Skipping." + else + if [ "$ID" = "ubuntu" ] || [ "$ID" = "debian" ]; then + apt-get -y install --no-install-recommends docker-ce-cli${cli_version_suffix} docker-ce${engine_version_suffix} + # Install compose + apt-mark hold docker-ce docker-ce-cli + apt-get -y install --no-install-recommends docker-compose-plugin || echo "(*) Package docker-compose-plugin (Docker Compose v2) not available for OS ${ID} ${VERSION_CODENAME} (${architecture}). Skipping." + + + elif [ "${USE_MOBY}" = "true" ] && { [ "$ID" = "fedora" ] || [ "$ID_LIKE" = "rhel" ]; }; then + install_docker_or_moby + + elif [ "${USE_MOBY}" = "false" ] && { [ "$ID" = "fedora" ] || [ "$ID_LIKE" = "rhel" ]; }; then + + #kmod package is required for modprobe + dnf install -y kmod iptables procps-ng + # Load iptable_nat module for docker-in-docker. + # See: + # - https://github.com/ublue-os/bluefin/issues/2365 + # - https://github.com/devcontainers/features/issues/1235 + mkdir -p /etc/modules-load.d && cat >>/etc/modules-load.d/ip_tables.conf << 'EOF' + iptable_nat +EOF + + # https://github.com/devcontainers/features/issues/1235 + if uname -r | grep -q '\.fc'; then + sudo update-alternatives --set iptables /usr/sbin/iptables-nft + fi + + # Get Fedora release version (e.g. 38, 39) + FEDORA_VERSION=$(rpm -E %fedora) + + echo "Detected Fedora version: $FEDORA_VERSION" + + echo "Installing dnf-plugins-core..." + if ! dnf install -y dnf-plugins-core; then + echo "⚠️ Failed to install dnf-plugins-core. Falling back to Moby." + install_docker_or_moby + exit 0 + fi + echo "Setting up Docker CE repo..." + if ! dnf config-manager --add-repo https://download.docker.com/linux/fedora/docker-ce.repo; then + echo "⚠️ Failed to add Docker CE repo. Falling back to Moby." + install_docker_or_moby + exit 0 + fi + + # Try installing Docker CE with fallback to Moby + echo "Attempting to install Docker CE..." + + set +e + dnf install -y docker docker-ce docker-ce-cli containerd.io + DOCKER_INSTALL_EXIT_CODE=$? + set -e + + if [ $DOCKER_INSTALL_EXIT_CODE -ne 0 ] || ! command -v docker >/dev/null || ! command -v dockerd >/dev/null; then + echo "⚠️ Docker CE installation appears incomplete or failed — falling back to Moby." + + install_docker_or_moby + + # Optional: symlink to match docker-ce command names + ln -sf /usr/bin/moby-engine /usr/bin/dockerd || true + else + echo "✅ Docker CE installed successfully!" + fi + + # Create docker group if missing + if ! getent group docker > /dev/null; then + echo "Creating 'docker' group..." + groupadd docker + fi + + # Add user to docker group + USERNAME=${USERNAME:-vscode} + echo "Adding user '$USERNAME' to docker group..." + usermod -aG docker "$USERNAME" + + # Final message + echo "✅ Docker or Moby installed and user configured." + else + if { [ "$ID" = "fedora" ] || [ "$ID_LIKE" = "rhel" ]; }; then + echo "❌ Unsupported OS or configuration. Exiting." + exit 1 + fi fi + echo "Finished installing Docker / Moby!" fi -echo "Finished installing docker / moby!" docker_home="/usr/libexec/docker" cli_plugins_dir="${docker_home}/cli-plugins" # fallback for docker-compose fallback_compose(){ - local url=$1 - local repo_url=$(get_github_api_repo_url "$url") - echo -e "\n(!) Failed to fetch the latest artifacts for docker-compose v${compose_version}..." - get_previous_version "${url}" "${repo_url}" compose_version - echo -e "\nAttempting to install v${compose_version}" - curl -fsSL "https://github.com/docker/compose/releases/download/v${compose_version}/docker-compose-linux-${target_compose_arch}" -o ${docker_compose_path} +local url=$1 +local repo_url=$(get_github_api_repo_url "$url") +echo -e "\n Failed to fetch the latest artifacts for docker-compose v${compose_version}" +get_previous_version "${url}" "${repo_url}" compose_version +echo -e "\nAttempting to install v${compose_version}" +curl -fsSL "https://github.com/docker/compose/releases/download/v${compose_version}/docker-compose-linux-${target_compose_arch}" -o ${docker_compose_path} } # If 'docker-compose' command is to be included if [ "${DOCKER_DASH_COMPOSE_VERSION}" != "none" ]; then - case "${architecture}" in - amd64) target_compose_arch=x86_64 ;; - arm64) target_compose_arch=aarch64 ;; - *) - echo "(!) Docker in docker does not support machine architecture '$architecture'. Please use an x86-64 or ARM64 machine." - exit 1 - esac - - docker_compose_path="/usr/local/bin/docker-compose" - if [ "${DOCKER_DASH_COMPOSE_VERSION}" = "v1" ]; then - err "The final Compose V1 release, version 1.29.2, was May 10, 2021. These packages haven't received any security updates since then. Use at your own risk." - INSTALL_DOCKER_COMPOSE_SWITCH="false" - - if [ "${target_compose_arch}" = "x86_64" ]; then - echo "(*) Installing docker compose v1..." - curl -fsSL "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-Linux-x86_64" -o ${docker_compose_path} - chmod +x ${docker_compose_path} - - # Download the SHA256 checksum - DOCKER_COMPOSE_SHA256="$(curl -sSL "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-Linux-x86_64.sha256" | awk '{print $1}')" - echo "${DOCKER_COMPOSE_SHA256} ${docker_compose_path}" > docker-compose.sha256sum - sha256sum -c docker-compose.sha256sum --ignore-missing - elif [ "${VERSION_CODENAME}" = "bookworm" ]; then - err "Docker compose v1 is unavailable for 'bookworm' on Arm64. Kindly switch to use v2" - exit 1 - else - # Use pip to get a version that runs on this architecture - check_packages python3-minimal python3-pip libffi-dev python3-venv - echo "(*) Installing docker compose v1 via pip..." - export PYTHONUSERBASE=/usr/local - pip3 install --disable-pip-version-check --no-cache-dir --user "Cython<3.0" pyyaml wheel docker-compose --no-build-isolation - fi - else - compose_version=${DOCKER_DASH_COMPOSE_VERSION#v} - docker_compose_url="https://github.com/docker/compose" - find_version_from_git_tags compose_version "$docker_compose_url" "tags/v" - echo "(*) Installing docker-compose ${compose_version}..." - curl -fsSL "https://github.com/docker/compose/releases/download/v${compose_version}/docker-compose-linux-${target_compose_arch}" -o ${docker_compose_path} || { - echo -e "\n(!) Failed to fetch the latest artifacts for docker-compose v${compose_version}..." - fallback_compose "$docker_compose_url" - } +case "${architecture}" in +amd64) target_compose_arch=x86_64 ;; +arm64) target_compose_arch=aarch64 ;; +*) +echo " Docker in docker does not support machine architecture '$architecture'. Please use an x86-64 or ARM64 machine." +exit 1 +esac + +docker_compose_path="/usr/local/bin/docker-compose" +if [ "${DOCKER_DASH_COMPOSE_VERSION}" = "v1" ]; then +err "The final Compose V1 release, version 1.29.2, was May 10, 2021. These packages haven't received any security updates since then. Use at your own risk." +INSTALL_DOCKER_COMPOSE_SWITCH="false" + +if [ "${target_compose_arch}" = "x86_64" ]; then +echo "(*) Installing docker compose v1..." +curl -fsSL "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-Linux-x86_64" -o ${docker_compose_path} +chmod +x ${docker_compose_path} + +# Download the SHA256 checksum +DOCKER_COMPOSE_SHA256="$(curl -sSL "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-Linux-x86_64.sha256" | awk '{print $1}')" +echo "${DOCKER_COMPOSE_SHA256} ${docker_compose_path}" > docker-compose.sha256sum +sha256sum -c docker-compose.sha256sum --ignore-missing +elif [ "${VERSION_CODENAME}" = "bookworm" ]; then +err "Docker compose v1 is unavailable for 'bookworm' on Arm64. Kindly switch to use v2" +exit 1 +else +# Use pip to get a version that runs on this architecture +check_packages python3-minimal python3-pip libffi-dev python3-venv +echo "(*) Installing docker compose v1 via pip..." +export PYTHONUSERBASE=/usr/local +pip3 install --disable-pip-version-check --no-cache-dir --user "Cython<3.0" pyyaml wheel docker-compose --no-build-isolation +fi +else +compose_version="${DOCKER_DASH_COMPOSE_VERSION#v}" +docker_compose_url="https://github.com/docker/compose" +find_version_from_git_tags compose_version "$docker_compose_url" "tags/v" +echo "(*) Installing docker-compose ${compose_version}..." +curl -fsSL "https://github.com/docker/compose/releases/download/compose_version/docker-compose-linux-${target_compose_arch}" -o ${docker_compose_path} || { +echo -e "\n(!) Failed to fetch the latest artifacts for docker-compose v${compose_version}..." +fallback_compose "$docker_compose_url" +} - chmod +x ${docker_compose_path} +chmod +x ${docker_compose_path} - # Download the SHA256 checksum - DOCKER_COMPOSE_SHA256="$(curl -sSL "https://github.com/docker/compose/releases/download/v${compose_version}/docker-compose-linux-${target_compose_arch}.sha256" | awk '{print $1}')" - echo "${DOCKER_COMPOSE_SHA256} ${docker_compose_path}" > docker-compose.sha256sum - sha256sum -c docker-compose.sha256sum --ignore-missing +# Download the SHA256 checksum +DOCKER_COMPOSE_SHA256="$(curl -sSL "https://github.com/docker/compose/releases/download/v${compose_version}/docker-compose-linux-${target_compose_arch}.sha256" | awk '{print $1}')" +echo "${DOCKER_COMPOSE_SHA256} ${docker_compose_path}" > docker-compose.sha256sum +sha256sum -c docker-compose.sha256sum --ignore-missing - mkdir -p ${cli_plugins_dir} - cp ${docker_compose_path} ${cli_plugins_dir} - fi +mkdir -p ${cli_plugins_dir} +cp ${docker_compose_path} ${cli_plugins_dir} +fi fi # fallback method for compose-switch fallback_compose-switch() { - local url=$1 - local repo_url=$(get_github_api_repo_url "$url") - echo -e "\n(!) Failed to fetch the latest artifacts for compose-switch v${compose_switch_version}..." - get_previous_version "$url" "$repo_url" compose_switch_version - echo -e "\nAttempting to install v${compose_switch_version}" - curl -fsSL "https://github.com/docker/compose-switch/releases/download/v${compose_switch_version}/docker-compose-linux-${architecture}" -o /usr/local/bin/compose-switch +local url=$1 +local repo_url=$(get_github_api_repo_url "$url") +echo -e "\n(!) Failed to fetch the latest artifacts for compose-switch v${compose_switch_version}..." +get_previous_version "$url" "$repo_url" compose_switch_version +echo -e "\nAttempting to install v${compose_switch_version}" +curl -fsSL "https://github.com/docker/compose-switch/releases/download/v${compose_switch_version}/docker-compose-linux-${architecture}" -o /usr/local/bin/compose-switch } # Install docker-compose switch if not already installed - https://github.com/docker/compose-switch#manual-installation if [ "${INSTALL_DOCKER_COMPOSE_SWITCH}" = "true" ] && ! type compose-switch > /dev/null 2>&1; then - if type docker-compose > /dev/null 2>&1; then - echo "(*) Installing compose-switch..." - current_compose_path="$(which docker-compose)" - target_compose_path="$(dirname "${current_compose_path}")/docker-compose-v1" - compose_switch_version="latest" - compose_switch_url="https://github.com/docker/compose-switch" - find_version_from_git_tags compose_switch_version "$compose_switch_url" - curl -fsSL "https://github.com/docker/compose-switch/releases/download/v${compose_switch_version}/docker-compose-linux-${architecture}" -o /usr/local/bin/compose-switch || fallback_compose-switch "$compose_switch_url" - chmod +x /usr/local/bin/compose-switch - # TODO: Verify checksum once available: https://github.com/docker/compose-switch/issues/11 - # Setup v1 CLI as alternative in addition to compose-switch (which maps to v2) - mv "${current_compose_path}" "${target_compose_path}" - update-alternatives --install ${docker_compose_path} docker-compose /usr/local/bin/compose-switch 99 - update-alternatives --install ${docker_compose_path} docker-compose "${target_compose_path}" 1 - else - err "Skipping installation of compose-switch as docker compose is unavailable..." - fi +if type docker-compose > /dev/null 2>&1; then +echo "(*) Installing compose-switch..." +current_compose_path="$(which docker-compose)" +target_compose_path="$(dirname "${current_compose_path}")/docker-compose-v1" +compose_switch_version="latest" +compose_switch_url="https://github.com/docker/compose-switch" +find_version_from_git_tags compose_switch_version "$compose_switch_url" +curl -fsSL "https://github.com/docker/compose-switch/releases/download/v${compose_switch_version}/docker-compose-linux-${architecture}" -o /usr/local/bin/compose-switch || fallback_compose-switch "$compose_switch_url" +chmod +x /usr/local/bin/compose-switch +# TODO: Verify checksum once available: https://github.com/docker/compose-switch/issues/11 +# Setup v1 CLI as alternative in addition to compose-switch (which maps to v2) +mv "${current_compose_path}" "${target_compose_path}" +update-alternatives --install ${docker_compose_path} docker-compose /usr/local/bin/compose-switch 99 +update-alternatives --install ${docker_compose_path} docker-compose "${target_compose_path}" 1 +else +err "Skipping installation of compose-switch as docker compose is unavailable..." +fi fi # If init file already exists, exit if [ -f "/usr/local/share/docker-init.sh" ]; then - echo "/usr/local/share/docker-init.sh already exists, so exiting." - # Clean up - rm -rf /var/lib/apt/lists/* - exit 0 +echo "/usr/local/share/docker-init.sh already exists, so exiting." +# Clean up +rm -rf /var/lib/apt/lists/* +exit 0 fi echo "docker-init doesn't exist, adding..." if ! cat /etc/group | grep -e "^docker:" > /dev/null 2>&1; then - groupadd -r docker +groupadd -r docker fi usermod -aG docker ${USERNAME} # fallback for docker/buildx fallback_buildx() { - local url=$1 - local repo_url=$(get_github_api_repo_url "$url") - echo -e "\n(!) Failed to fetch the latest artifacts for docker buildx v${buildx_version}..." - get_previous_version "$url" "$repo_url" buildx_version - buildx_file_name="buildx-v${buildx_version}.linux-${architecture}" - echo -e "\nAttempting to install v${buildx_version}" - wget https://github.com/docker/buildx/releases/download/v${buildx_version}/${buildx_file_name} +local url=$1 +local repo_url=$(get_github_api_repo_url "$url") +echo -e "\nFailed to fetch the latest artifacts for docker buildx v${buildx_version}..." +get_previous_version "$url" "$repo_url" buildx_version +buildx_file_name="buildx-v${buildx_version}.linux-amd64" +echo -e "\nAttempting to install v${buildx_version}" +wget https://github.com/docker/buildx/releases/download/v${buildx_version}/${buildx_file_name} } - + if [ "${INSTALL_DOCKER_BUILDX}" = "true" ]; then - buildx_version="latest" - docker_buildx_url="https://github.com/docker/buildx" - find_version_from_git_tags buildx_version "$docker_buildx_url" "refs/tags/v" - echo "(*) Installing buildx ${buildx_version}..." - buildx_file_name="buildx-v${buildx_version}.linux-${architecture}" - - cd /tmp - wget https://github.com/docker/buildx/releases/download/v${buildx_version}/${buildx_file_name} || fallback_buildx "$docker_buildx_url" - - docker_home="/usr/libexec/docker" - cli_plugins_dir="${docker_home}/cli-plugins" - - mkdir -p ${cli_plugins_dir} - mv ${buildx_file_name} ${cli_plugins_dir}/docker-buildx - chmod +x ${cli_plugins_dir}/docker-buildx - - chown -R "${USERNAME}:docker" "${docker_home}" - chmod -R g+r+w "${docker_home}" - find "${docker_home}" -type d -print0 | xargs -n 1 -0 chmod g+s +buildx_version="latest" +docker_buildx_url="https://github.com/docker/buildx" +find_version_from_git_tags buildx_version "$docker_buildx_url" "refs/tags/v" +echo '(*) Installing buildx ${buildx_version}...' +buildx_file_name="buildx-v${buildx_version}.linux-${architecture}" + +cd /tmp +wget https://github.com/docker/buildx/releases/download/v${buildx_version}/${buildx_file_name} || fallback_buildx "$docker_buildx_url" + +docker_home="/usr/libexec/docker" +cli_plugins_dir="${docker_home}/cli-plugins" + +mkdir -p "${cli_plugins_dir}" +mv "${buildx_file_name}" "${cli_plugins_dir}/docker-buildx" +chmod +x "${cli_plugins_dir}/docker-buildx" + +chown -R "${USERNAME}:docker" "${docker_home}" +chmod -R g+r+w "${docker_home}" +find "${docker_home}" -type d -print0 | xargs -n 1 -0 chmod g+s fi DOCKER_DEFAULT_IP6_TABLES="" if [ "$DISABLE_IP6_TABLES" == true ]; then - requested_version="" - # checking whether the version requested either is in semver format or just a number denoting the major version - # and, extracting the major version number out of the two scenarios - semver_regex="^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(-([0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*))?(\+([0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*))?$" - if echo "$DOCKER_VERSION" | grep -Eq $semver_regex; then - requested_version=$(echo $DOCKER_VERSION | cut -d. -f1) - elif echo "$DOCKER_VERSION" | grep -Eq "^[1-9][0-9]*$"; then - requested_version=$DOCKER_VERSION - fi - if [ "$DOCKER_VERSION" = "latest" ] || [[ -n "$requested_version" && "$requested_version" -ge 27 ]] ; then - DOCKER_DEFAULT_IP6_TABLES="--ip6tables=false" - echo "(!) As requested, passing '${DOCKER_DEFAULT_IP6_TABLES}'" - fi +requested_version="" +# checking whether the version requested either is in semver format or just a number denoting the major version +# and, extracting the major version number out of the two scenarios +semver_regex='^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(-([0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*))?(\+([0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*))?$' +if echo "$DOCKER_VERSION" | grep -Eq $semver_regex; then +requested_version=$(echo $DOCKER_VERSION | cut -d. -f1) +elif echo "$DOCKER_VERSION" | grep -Eq "^[1-9][0-9]*$"; then +requested_version=$DOCKER_VERSION +fi +if [ "$DOCKER_VERSION" = "latest" ] || [[ -n "$requested_version" && "$requested_version" -ge 27 ]]; then +DOCKER_DEFAULT_IP6_TABLES="--ip6tables=false" +echo "! As requested, passing ${DOCKER_DEFAULT_IP6_TABLES}" +fi fi tee /usr/local/share/docker-init.sh > /dev/null \ @@ -585,8 +740,9 @@ dockerd_start="AZURE_DNS_AUTO_DETECTION=${AZURE_DNS_AUTO_DETECTION} DOCKER_DEFAU INNEREOF )" + sudo_if() { - COMMAND="$*" + COMMAND="$*" if [ "$(id -u)" -ne 0 ]; then sudo $COMMAND @@ -607,6 +763,7 @@ do eval "${dockerd_start}" fi + # Wait up to 10 seconds for Docker to respond retry_count=0 until [ "${docker_ok}" = "true" ] || [ "${retry_count}" -eq "5" ]; do diff --git a/test/docker-in-docker/fedora_kernel.sh b/test/docker-in-docker/fedora_kernel.sh new file mode 100644 index 000000000..b369c01f0 --- /dev/null +++ b/test/docker-in-docker/fedora_kernel.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +set -e + +# Optional: Import test library +source dev-container-features-test-lib + +# Function to check iptables version +iptablesCheck() { + if command -v iptables > /dev/null 2>&1; then + if iptables --version > /dev/null 2>&1; then + echo "✔️ iptables is installed and functional." + else + echo "❌ iptables is installed but not functional." + fi + else + echo "❌ iptables command not found." + fi +} + +# Function to check Fedora kernel version +kernelVersionCheck() { + if uname -r > /dev/null 2>&1; then + echo "✔️ Kernel version: $(uname -r)" + else + echo "❌ Unable to retrieve kernel version." + fi +} + +# Run checks +check "iptables version" iptablesCheck +check "kernel version" kernelVersionCheck + +# Report results +reportResults \ No newline at end of file diff --git a/test/docker-in-docker/fedora_moby.sh b/test/docker-in-docker/fedora_moby.sh new file mode 100644 index 000000000..b369c01f0 --- /dev/null +++ b/test/docker-in-docker/fedora_moby.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +set -e + +# Optional: Import test library +source dev-container-features-test-lib + +# Function to check iptables version +iptablesCheck() { + if command -v iptables > /dev/null 2>&1; then + if iptables --version > /dev/null 2>&1; then + echo "✔️ iptables is installed and functional." + else + echo "❌ iptables is installed but not functional." + fi + else + echo "❌ iptables command not found." + fi +} + +# Function to check Fedora kernel version +kernelVersionCheck() { + if uname -r > /dev/null 2>&1; then + echo "✔️ Kernel version: $(uname -r)" + else + echo "❌ Unable to retrieve kernel version." + fi +} + +# Run checks +check "iptables version" iptablesCheck +check "kernel version" kernelVersionCheck + +# Report results +reportResults \ No newline at end of file diff --git a/test/docker-in-docker/scenarios.json b/test/docker-in-docker/scenarios.json index 57681b799..bc3277c17 100644 --- a/test/docker-in-docker/scenarios.json +++ b/test/docker-in-docker/scenarios.json @@ -166,5 +166,35 @@ }, "remoteUser": "vscode", "onCreateCommand": "docker ps && sleep 5s && docker ps" + }, + "fedora_kernel": { + "image": "fedora:41", + "features": { + "docker-in-docker": { + "iptables": "true", + "moby": "true", + "installDockerBuildx": true, + "dockerDashComposeVersion": "latest" + } + } + }, + "fedora_moby": { + "image": "fedora:41", + "features": { + "docker-in-docker": { + "iptables": "true", + "moby": "false", + "installDockerBuildx": true, + "dockerDashComposeVersion": "latest" + } + }, + + "mounts": [ + { + "source":"/var/run/docker.sock", + "target":"/var/run/docker.sock", + "type":"bind" + } + ] + } } -}