diff --git a/containers/azure-functions-java-11/.devcontainer/devcontainer.json b/containers/azure-functions-java-11/.devcontainer/devcontainer.json index 97e9f0228e..9b72091736 100644 --- a/containers/azure-functions-java-11/.devcontainer/devcontainer.json +++ b/containers/azure-functions-java-11/.devcontainer/devcontainer.json @@ -9,7 +9,6 @@ "vscode": { // Set *default* container specific settings.json values on container create. "settings": { - "java.home": "/usr/lib/jvm/zulu-11-azure-amd64" }, // Add the IDs of extensions you want installed when the container is created. diff --git a/containers/azure-functions-java-8/.devcontainer/devcontainer.json b/containers/azure-functions-java-8/.devcontainer/devcontainer.json index 00bbfbba4f..6c9b21381e 100644 --- a/containers/azure-functions-java-8/.devcontainer/devcontainer.json +++ b/containers/azure-functions-java-8/.devcontainer/devcontainer.json @@ -9,7 +9,7 @@ "vscode": { // Set *default* container specific settings.json values on container create. "settings": { - "java.home": "/usr/lib/jvm/zulu-11-azure-amd64", + "java.import.gradle.java.home": "/usr/lib/jvm/zulu-8-amd64", "java.configuration.runtimes": [ { "default": true, diff --git a/containers/clojure/.devcontainer/devcontainer.json b/containers/clojure/.devcontainer/devcontainer.json index 1625ac689e..620df84461 100644 --- a/containers/clojure/.devcontainer/devcontainer.json +++ b/containers/clojure/.devcontainer/devcontainer.json @@ -23,7 +23,6 @@ "vscode": { // Set *default* container specific settings.json values on container create. "settings": { - "java.home": "/docker-java-home" }, // Add the IDs of extensions you want installed when the container is created. diff --git a/containers/java-8/.devcontainer/Dockerfile b/containers/java-8/.devcontainer/Dockerfile index 95689d0f30..5da2d4ec1f 100644 --- a/containers/java-8/.devcontainer/Dockerfile +++ b/containers/java-8/.devcontainer/Dockerfile @@ -1,6 +1,6 @@ # [Choice] Debian OS version (use bullseye on local arm64/Apple Silicon): buster, bullseye ARG VARIANT="buster" -FROM mcr.microsoft.com/vscode/devcontainers/java:0-8-${VARIANT} +FROM mcr.microsoft.com/vscode/devcontainers/java:1-8-${VARIANT} # [Option] Install Maven ARG INSTALL_MAVEN="false" diff --git a/containers/java-8/.devcontainer/base.Dockerfile b/containers/java-8/.devcontainer/base.Dockerfile index d7993a7791..1de87deef7 100644 --- a/containers/java-8/.devcontainer/base.Dockerfile +++ b/containers/java-8/.devcontainer/base.Dockerfile @@ -1,6 +1,6 @@ # [Choice] Debian OS version (use bullseye on local arm64/Apple Silicon): buster, bullseye ARG VARIANT="bullseye" -FROM mcr.microsoft.com/vscode/devcontainers/java:0-11-${VARIANT} +FROM mcr.microsoft.com/vscode/devcontainers/base:${VARIANT} # Install JDK 8 and optionally Maven and Gradle - version of "" installs latest ARG JDK8_VERSION="" @@ -8,16 +8,27 @@ ARG INSTALL_MAVEN="false" ARG MAVEN_VERSION="" ARG INSTALL_GRADLE="false" ARG GRADLE_VERSION="" -COPY library-scripts/meta.env /usr/local/etc/vscode-dev-containers -RUN su vscode -c "umask 0002 && . /usr/local/sdkman/bin/sdkman-init.sh && if [ "${JDK8_VERSION}" = "" ]; then \ - sdk install java \$(sdk ls java | grep -m 1 -o ' 8.*.-tem ' | awk '{print \$NF}'); \ - else sdk install java '${JDK8_VERSION}'; fi" \ - && if [ "${INSTALL_MAVEN}" = "true" ]; then su vscode -c "umask 0002 && . /usr/local/sdkman/bin/sdkman-init.sh && sdk install maven \"${MAVEN_VERSION}\""; fi \ - && if [ "${INSTALL_GRADLE}" = "true" ]; then su vscode -c "umask 0002 && . /usr/local/sdkman/bin/sdkman-init.sh && sdk install gradle \"${GRADLE_VERSION}\""; fi +# Copy library scripts to execute +COPY library-scripts/*.sh library-scripts/*.env /tmp/library-scripts/ + +ENV SDKMAN_DIR="/usr/local/sdkman" +ENV PATH="${SDKMAN_DIR}/candidates/java/current/bin:${PATH}:${SDKMAN_DIR}/candidates/maven/current/bin:${SDKMAN_DIR}/candidates/gradle/current/bin" +RUN if [ "${JDK8_VERSION}" = "" ]; then bash /tmp/library-scripts/java-debian.sh "8" "${SDKMAN_DIR}" "${USERNAME}" "true" \ + else bash /tmp/library-scripts/java-debian.sh "${JDK8_VERSION}" "${SDKMAN_DIR}" "${USERNAME}" "true"; fi \ + && if [ "${INSTALL_MAVEN}" = "true" ]; then bash /tmp/library-scripts/maven-debian.sh "${MAVEN_VERSION:-latest}" "${SDKMAN_DIR}" ${USERNAME} "true"; fi \ + && if [ "${INSTALL_GRADLE}" = "true" ]; then bash /tmp/library-scripts/gradle-debian.sh "${GRADLE_VERSION:-latest}" "${SDKMAN_DIR}" ${USERNAME} "true"; fi \ + && apt-get clean -y && rm -rf /var/lib/apt/lists/* # [Choice] Node.js version: none, lts/*, 16, 14, 12, 10 ARG NODE_VERSION="none" -RUN if [ "${NODE_VERSION}" != "none" ]; then su vscode -c "umask 0002 && . /usr/local/share/nvm/nvm.sh && nvm install ${NODE_VERSION} 2>&1"; fi +ENV NVM_DIR=/usr/local/share/nvm +ENV NVM_SYMLINK_CURRENT=true \ + PATH="${NVM_DIR}/current/bin:${PATH}" +RUN bash /tmp/library-scripts/node-debian.sh "${NVM_DIR}" "${NODE_VERSION}" "${USERNAME}" \ + && apt-get clean -y && rm -rf /var/lib/apt/lists/* + +# Remove library scripts for final image +RUN rm -rf /tmp/library-scripts # [Optional] Uncomment this section to install additional OS packages. # RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ diff --git a/containers/java-8/.devcontainer/devcontainer.json b/containers/java-8/.devcontainer/devcontainer.json index 29d334d044..5d104164a2 100644 --- a/containers/java-8/.devcontainer/devcontainer.json +++ b/containers/java-8/.devcontainer/devcontainer.json @@ -19,7 +19,6 @@ "vscode": { // Set *default* container specific settings.json values on container create. "settings": { - "java.home": "/docker-java-home", "java.import.gradle.java.home": "/usr/local/sdkman/candidates/java/current", "java.configuration.runtimes": [{ "default": true, diff --git a/containers/java-8/.devcontainer/library-scripts/gradle-debian.sh b/containers/java-8/.devcontainer/library-scripts/gradle-debian.sh new file mode 100644 index 0000000000..2fe7fa929e --- /dev/null +++ b/containers/java-8/.devcontainer/library-scripts/gradle-debian.sh @@ -0,0 +1,133 @@ +#!/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. +#------------------------------------------------------------------------------------------------------------- +# +# Docs: https://github.com/microsoft/vscode-dev-containers/blob/main/script-library/docs/gradle.md +# Maintainer: The VS Code and Codespaces Teams +# +# Syntax: ./gradle-debian.sh [Gradle version] [SDKMAN_DIR] [non-root user] [Update rc files flag] + +GRADLE_VERSION=${1:-"latest"} +export SDKMAN_DIR=${2:-"/usr/local/sdkman"} +USERNAME=${3:-"automatic"} +UPDATE_RC=${4:-"true"} + +set -e + +if [ "$(id -u)" -ne 0 ]; then + echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.' + exit 1 +fi + +# Ensure that login shells get the correct path if the user updated the PATH using ENV. +rm -f /etc/profile.d/00-restore-env.sh +echo "export PATH=${PATH//$(sh -lc 'echo $PATH')/\$PATH}" > /etc/profile.d/00-restore-env.sh +chmod +x /etc/profile.d/00-restore-env.sh + +# 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 +elif [ "${USERNAME}" = "none" ] || ! id -u ${USERNAME} > /dev/null 2>&1; then + USERNAME=root +fi + +updaterc() { + if [ "${UPDATE_RC}" = "true" ]; then + echo "Updating /etc/bash.bashrc and /etc/zsh/zshrc..." + if [[ "$(cat /etc/bash.bashrc)" != *"$1"* ]]; then + echo -e "$1" >> /etc/bash.bashrc + fi + if [ -f "/etc/zsh/zshrc" ] && [[ "$(cat /etc/zsh/zshrc)" != *"$1"* ]]; then + echo -e "$1" >> /etc/zsh/zshrc + fi + fi +} + +# Function to run apt-get if needed +apt_get_update_if_needed() +{ + if [ ! -d "/var/lib/apt/lists" ] || [ "$(ls /var/lib/apt/lists/ | wc -l)" = "0" ]; then + echo "Running apt-get update..." + apt-get update + else + echo "Skipping apt-get update." + fi +} + +# Checks if packages are installed and installs them if not +check_packages() { + if ! dpkg -s "$@" > /dev/null 2>&1; then + apt_get_update_if_needed + apt-get -y install --no-install-recommends "$@" + fi +} + +# Use SDKMAN to install something using a partial version match +sdk_install() { + local install_type=$1 + local requested_version=$2 + local prefix=$3 + local suffix="${4:-"\\s*"}" + local full_version_check=${5:-".*-[a-z]+"} + if [ "${requested_version}" = "none" ]; then return; fi + # Blank will install latest stable version + if [ "${requested_version}" = "lts" ] || [ "${requested_version}" = "default" ]; then + requested_version="" + elif echo "${requested_version}" | grep -oE "${full_version_check}" > /dev/null 2>&1; then + echo "${requested_version}" + else + local regex="${prefix}\\K[0-9]+\\.[0-9]+\\.[0-9]+${suffix}" + local version_list="$(. ${SDKMAN_DIR}/bin/sdkman-init.sh && sdk list ${install_type} 2>&1 | grep -oP "${regex}" | tr -d ' ' | sort -rV)" + if [ "${requested_version}" = "latest" ] || [ "${requested_version}" = "current" ]; then + requested_version="$(echo "${version_list}" | head -n 1)" + else + set +e + requested_version="$(echo "${version_list}" | grep -E -m 1 "^${requested_version//./\\.}([\\.\\s]|$)")" + set -e + fi + if [ -z "${requested_version}" ] || ! echo "${version_list}" | grep "^${requested_version//./\\.}$" > /dev/null 2>&1; then + echo -e "Version $2 not found. Available versions:\n${version_list}" >&2 + exit 1 + fi + fi + su ${USERNAME} -c "umask 0002 && . ${SDKMAN_DIR}/bin/sdkman-init.sh && sdk install ${install_type} ${requested_version} && sdk flush archives && sdk flush temp" +} + +export DEBIAN_FRONTEND=noninteractive + +# Install dependencies +check_packages curl ca-certificates zip unzip sed + +# Install sdkman if not installed +if [ ! -d "${SDKMAN_DIR}" ]; then + # Create sdkman group, dir, and set sticky bit + if ! cat /etc/group | grep -e "^sdkman:" > /dev/null 2>&1; then + groupadd -r sdkman + fi + usermod -a -G sdkman ${USERNAME} + umask 0002 + # Install SDKMAN + curl -sSL "https://get.sdkman.io?rcupdate=false" | bash + chown -R :sdkman ${SDKMAN_DIR} + find ${SDKMAN_DIR} -type d | xargs -d '\n' chmod g+s + # Add sourcing of sdkman into bashrc/zshrc files (unless disabled) + updaterc "export SDKMAN_DIR=${SDKMAN_DIR}\n. \${SDKMAN_DIR}/bin/sdkman-init.sh" +fi + +# Install gradle +sdk_install gradle ${GRADLE_VERSION} '\s\s' '\s\s' '^[0-9]+\.[0-9]+\.[0-9]+$' +updaterc '[ -z "${GRADLE_USER_HOME}" ] && export GRADLE_USER_HOME=${HOME}/.gradle' + +echo "Done!" diff --git a/containers/java-8/.devcontainer/library-scripts/java-debian.sh b/containers/java-8/.devcontainer/library-scripts/java-debian.sh new file mode 100644 index 0000000000..f5880cdebb --- /dev/null +++ b/containers/java-8/.devcontainer/library-scripts/java-debian.sh @@ -0,0 +1,145 @@ +#!/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. +#------------------------------------------------------------------------------------------------------------- +# +# Docs: https://github.com/microsoft/vscode-dev-containers/blob/main/script-library/docs/java.md +# Maintainer: The VS Code and Codespaces Teams +# +# Syntax: ./java-debian.sh [JDK version] [SDKMAN_DIR] [non-root user] [Add to rc files flag] + +JAVA_VERSION=${1:-"lts"} +export SDKMAN_DIR=${2:-"/usr/local/sdkman"} +USERNAME=${3:-"automatic"} +UPDATE_RC=${4:-"true"} + +set -e + +if [ "$(id -u)" -ne 0 ]; then + echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.' + exit 1 +fi + +# Ensure that login shells get the correct path if the user updated the PATH using ENV. +rm -f /etc/profile.d/00-restore-env.sh +echo "export PATH=${PATH//$(sh -lc 'echo $PATH')/\$PATH}" > /etc/profile.d/00-restore-env.sh +chmod +x /etc/profile.d/00-restore-env.sh + +# 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 +elif [ "${USERNAME}" = "none" ] || ! id -u ${USERNAME} > /dev/null 2>&1; then + USERNAME=root +fi + +updaterc() { + if [ "${UPDATE_RC}" = "true" ]; then + echo "Updating /etc/bash.bashrc and /etc/zsh/zshrc..." + if [[ "$(cat /etc/bash.bashrc)" != *"$1"* ]]; then + echo -e "$1" >> /etc/bash.bashrc + fi + if [ -f "/etc/zsh/zshrc" ] && [[ "$(cat /etc/zsh/zshrc)" != *"$1"* ]]; then + echo -e "$1" >> /etc/zsh/zshrc + fi + fi +} + +# Function to run apt-get if needed +apt_get_update_if_needed() +{ + if [ ! -d "/var/lib/apt/lists" ] || [ "$(ls /var/lib/apt/lists/ | wc -l)" = "0" ]; then + echo "Running apt-get update..." + apt-get update + else + echo "Skipping apt-get update." + fi +} + +# Checks if packages are installed and installs them if not +check_packages() { + if ! dpkg -s "$@" > /dev/null 2>&1; then + apt_get_update_if_needed + apt-get -y install --no-install-recommends "$@" + fi +} + +# Use SDKMAN to install something using a partial version match +sdk_install() { + local install_type=$1 + local requested_version=$2 + local prefix=$3 + local suffix="${4:-"\\s*"}" + local full_version_check=${5:-".*-[a-z]+"} + if [ "${requested_version}" = "none" ]; then return; fi + # Blank will install latest stable version SDKMAN has + if [ "${requested_version}" = "lts" ] || [ "${requested_version}" = "default" ]; then + requested_version="" + elif echo "${requested_version}" | grep -oE "${full_version_check}" > /dev/null 2>&1; then + echo "${requested_version}" + else + local regex="${prefix}\\K[0-9]+\\.[0-9]+\\.[0-9]+${suffix}" + local version_list="$(. ${SDKMAN_DIR}/bin/sdkman-init.sh && sdk list ${install_type} 2>&1 | grep -oP "${regex}" | tr -d ' ' | sort -rV)" + if [ "${requested_version}" = "latest" ] || [ "${requested_version}" = "current" ]; then + requested_version="$(echo "${version_list}" | head -n 1)" + else + set +e + requested_version="$(echo "${version_list}" | grep -E -m 1 "^${requested_version//./\\.}([\\.\\s]|$)")" + set -e + fi + if [ -z "${requested_version}" ] || ! echo "${version_list}" | grep "^${requested_version//./\\.}$" > /dev/null 2>&1; then + echo -e "Version $2 not found. Available versions:\n${version_list}" >&2 + exit 1 + fi + fi + su ${USERNAME} -c "umask 0002 && . ${SDKMAN_DIR}/bin/sdkman-init.sh && sdk install ${install_type} ${requested_version} && sdk flush archives && sdk flush temp" +} + +export DEBIAN_FRONTEND=noninteractive + +architecture="$(uname -m)" +if [ "${architecture}" != "amd64" ] && [ "${architecture}" != "x86_64" ] && [ "${architecture}" != "arm64" ] && [ "${architecture}" != "aarch64" ]; then + echo "(!) Architecture $architecture unsupported" + exit 1 +fi + +# Install dependencies +check_packages curl ca-certificates zip unzip sed + +# Install sdkman if not installed +if [ ! -d "${SDKMAN_DIR}" ]; then + # Create sdkman group, dir, and set sticky bit + if ! cat /etc/group | grep -e "^sdkman:" > /dev/null 2>&1; then + groupadd -r sdkman + fi + usermod -a -G sdkman ${USERNAME} + umask 0002 + # Install SDKMAN + curl -sSL "https://get.sdkman.io?rcupdate=false" | bash + chown -R :sdkman ${SDKMAN_DIR} + find ${SDKMAN_DIR} -type d | xargs -d '\n' chmod g+s + # Add sourcing of sdkman into bashrc/zshrc files (unless disabled) + updaterc "export SDKMAN_DIR=${SDKMAN_DIR}\n. \${SDKMAN_DIR}/bin/sdkman-init.sh" +fi + +# Use Microsoft JDK for everything but JDK 8 +jdk_distro="ms" +if echo "${JAVA_VERSION}" | grep -E '^8([\s\.]|$)' > /dev/null 2>&1; then + jdk_distro="tem" +fi +if [ "${JAVA_VERSION}" = "lts" ]; then + JAVA_VERSION="17" +fi +sdk_install java ${JAVA_VERSION} "\\s*" "(\\.[a-z0-9]+)*-${jdk_distro}\\s*" ".*-[a-z]+$" + +echo "Done!" \ No newline at end of file diff --git a/containers/java-8/.devcontainer/library-scripts/maven-debian.sh b/containers/java-8/.devcontainer/library-scripts/maven-debian.sh new file mode 100644 index 0000000000..f8369f571f --- /dev/null +++ b/containers/java-8/.devcontainer/library-scripts/maven-debian.sh @@ -0,0 +1,133 @@ +#!/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. +#------------------------------------------------------------------------------------------------------------- +# +# Docs: https://github.com/microsoft/vscode-dev-containers/blob/main/script-library/docs/maven.md +# Maintainer: The VS Code and Codespaces Teams +# +# Syntax: ./maven-debian.sh [maven version] [SDKMAN_DIR] [non-root user] [Update rc files flag] + +MAVEN_VERSION=${1:-"latest"} +export SDKMAN_DIR=${2:-"/usr/local/sdkman"} +USERNAME=${3:-"automatic"} +UPDATE_RC=${4:-"true"} + +set -e + +if [ "$(id -u)" -ne 0 ]; then + echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.' + exit 1 +fi + +# Ensure that login shells get the correct path if the user updated the PATH using ENV. +rm -f /etc/profile.d/00-restore-env.sh +echo "export PATH=${PATH//$(sh -lc 'echo $PATH')/\$PATH}" > /etc/profile.d/00-restore-env.sh +chmod +x /etc/profile.d/00-restore-env.sh + +# 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 +elif [ "${USERNAME}" = "none" ] || ! id -u ${USERNAME} > /dev/null 2>&1; then + USERNAME=root +fi + +updaterc() { + if [ "${UPDATE_RC}" = "true" ]; then + echo "Updating /etc/bash.bashrc and /etc/zsh/zshrc..." + if [[ "$(cat /etc/bash.bashrc)" != *"$1"* ]]; then + echo -e "$1" >> /etc/bash.bashrc + fi + if [ -f "/etc/zsh/zshrc" ] && [[ "$(cat /etc/zsh/zshrc)" != *"$1"* ]]; then + echo -e "$1" >> /etc/zsh/zshrc + fi + fi +} + +# Function to run apt-get if needed +apt_get_update_if_needed() +{ + if [ ! -d "/var/lib/apt/lists" ] || [ "$(ls /var/lib/apt/lists/ | wc -l)" = "0" ]; then + echo "Running apt-get update..." + apt-get update + else + echo "Skipping apt-get update." + fi +} + +# Checks if packages are installed and installs them if not +check_packages() { + if ! dpkg -s "$@" > /dev/null 2>&1; then + apt_get_update_if_needed + apt-get -y install --no-install-recommends "$@" + fi +} + +# Use SDKMAN to install something using a partial version match +sdk_install() { + local install_type=$1 + local requested_version=$2 + local prefix=$3 + local suffix="${4:-"\\s*"}" + local full_version_check=${5:-".*-[a-z]+"} + if [ "${requested_version}" = "none" ]; then return; fi + # Blank will install latest stable version + if [ "${requested_version}" = "lts" ] || [ "${requested_version}" = "default" ]; then + requested_version="" + elif echo "${requested_version}" | grep -oE "${full_version_check}" > /dev/null 2>&1; then + echo "${requested_version}" + else + local regex="${prefix}\\K[0-9]+\\.[0-9]+\\.[0-9]+${suffix}" + local version_list="$(. ${SDKMAN_DIR}/bin/sdkman-init.sh && sdk list ${install_type} 2>&1 | grep -oP "${regex}" | tr -d ' ' | sort -rV)" + if [ "${requested_version}" = "latest" ] || [ "${requested_version}" = "current" ]; then + requested_version="$(echo "${version_list}" | head -n 1)" + else + set +e + requested_version="$(echo "${version_list}" | grep -E -m 1 "^${requested_version//./\\.}([\\.\\s]|$)")" + set -e + fi + if [ -z "${requested_version}" ] || ! echo "${version_list}" | grep "^${requested_version//./\\.}$" > /dev/null 2>&1; then + echo -e "Version $2 not found. Available versions:\n${version_list}" >&2 + exit 1 + fi + fi + su ${USERNAME} -c "umask 0002 && . ${SDKMAN_DIR}/bin/sdkman-init.sh && sdk install ${install_type} ${requested_version} && sdk flush archives && sdk flush temp" +} + +export DEBIAN_FRONTEND=noninteractive + +# Install dependencies +check_packages curl ca-certificates zip unzip sed + +# Install sdkman if not installed +if [ ! -d "${SDKMAN_DIR}" ]; then + # Create sdkman group, dir, and set sticky bit + if ! cat /etc/group | grep -e "^sdkman:" > /dev/null 2>&1; then + groupadd -r sdkman + fi + usermod -a -G sdkman ${USERNAME} + umask 0002 + # Install SDKMAN + curl -sSL "https://get.sdkman.io?rcupdate=false" | bash + chown -R :sdkman ${SDKMAN_DIR} + find ${SDKMAN_DIR} -type d | xargs -d '\n' chmod g+s + # Add sourcing of sdkman into bashrc/zshrc files (unless disabled) + updaterc "export SDKMAN_DIR=${SDKMAN_DIR}\n. \${SDKMAN_DIR}/bin/sdkman-init.sh" +fi + +# Install Maven +sdk_install maven ${MAVEN_VERSION} '\s\s' '\s\s' '^[0-9]+\.[0-9]+\.[0-9]+$' +updaterc '[ -z "$M2" ] && export M2=$HOME/.m2' + +echo "Done!" \ No newline at end of file diff --git a/containers/java-8/.devcontainer/library-scripts/node-debian.sh b/containers/java-8/.devcontainer/library-scripts/node-debian.sh new file mode 100644 index 0000000000..c3551689c9 --- /dev/null +++ b/containers/java-8/.devcontainer/library-scripts/node-debian.sh @@ -0,0 +1,169 @@ +#!/bin/bash +#------------------------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information. +#------------------------------------------------------------------------------------------------------------- +# +# Docs: https://github.com/microsoft/vscode-dev-containers/blob/main/script-library/docs/node.md +# Maintainer: The VS Code and Codespaces Teams +# +# Syntax: ./node-debian.sh [directory to install nvm] [node version to install (use "none" to skip)] [non-root user] [Update rc files flag] [install node-gyp deps] + +export NVM_DIR=${1:-"/usr/local/share/nvm"} +export NODE_VERSION=${2:-"lts"} +USERNAME=${3:-"automatic"} +UPDATE_RC=${4:-"true"} +INSTALL_TOOLS_FOR_NODE_GYP="${5:-true}" +export NVM_VERSION="0.38.0" + +set -e + +if [ "$(id -u)" -ne 0 ]; then + echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.' + exit 1 +fi + +# Ensure that login shells get the correct path if the user updated the PATH using ENV. +rm -f /etc/profile.d/00-restore-env.sh +echo "export PATH=${PATH//$(sh -lc 'echo $PATH')/\$PATH}" > /etc/profile.d/00-restore-env.sh +chmod +x /etc/profile.d/00-restore-env.sh + +# 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 +elif [ "${USERNAME}" = "none" ] || ! id -u ${USERNAME} > /dev/null 2>&1; then + USERNAME=root +fi + +updaterc() { + if [ "${UPDATE_RC}" = "true" ]; then + echo "Updating /etc/bash.bashrc and /etc/zsh/zshrc..." + if [[ "$(cat /etc/bash.bashrc)" != *"$1"* ]]; then + echo -e "$1" >> /etc/bash.bashrc + fi + if [ -f "/etc/zsh/zshrc" ] && [[ "$(cat /etc/zsh/zshrc)" != *"$1"* ]]; then + echo -e "$1" >> /etc/zsh/zshrc + fi + fi +} + +# Function to run apt-get if needed +apt_get_update_if_needed() +{ + if [ ! -d "/var/lib/apt/lists" ] || [ "$(ls /var/lib/apt/lists/ | wc -l)" = "0" ]; then + echo "Running apt-get update..." + apt-get update + else + echo "Skipping apt-get update." + fi +} + +# Checks if packages are installed and installs them if not +check_packages() { + if ! dpkg -s "$@" > /dev/null 2>&1; then + apt_get_update_if_needed + apt-get -y install --no-install-recommends "$@" + fi +} + +# Ensure apt is in non-interactive to avoid prompts +export DEBIAN_FRONTEND=noninteractive + +# Install dependencies +check_packages apt-transport-https curl ca-certificates tar gnupg2 dirmngr + +# Install yarn +if type yarn > /dev/null 2>&1; then + echo "Yarn already installed." +else + # Import key safely (new method rather than deprecated apt-key approach) and install + curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | gpg --dearmor > /usr/share/keyrings/yarn-archive-keyring.gpg + echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/yarn-archive-keyring.gpg] https://dl.yarnpkg.com/debian/ stable main" > /etc/apt/sources.list.d/yarn.list + apt-get update + apt-get -y install --no-install-recommends yarn +fi + +# Adjust node version if required +if [ "${NODE_VERSION}" = "none" ]; then + export NODE_VERSION= +elif [ "${NODE_VERSION}" = "lts" ]; then + export NODE_VERSION="lts/*" +fi + +# Create a symlink to the installed version for use in Dockerfile PATH statements +export NVM_SYMLINK_CURRENT=true + +# Install the specified node version if NVM directory already exists, then exit +if [ -d "${NVM_DIR}" ]; then + echo "NVM already installed." + if [ "${NODE_VERSION}" != "" ]; then + su ${USERNAME} -c ". $NVM_DIR/nvm.sh && nvm install ${NODE_VERSION} && nvm clear-cache" + fi + exit 0 +fi + +# Create nvm group, nvm dir, and set sticky bit +if ! cat /etc/group | grep -e "^nvm:" > /dev/null 2>&1; then + groupadd -r nvm +fi +umask 0002 +usermod -a -G nvm ${USERNAME} +mkdir -p ${NVM_DIR} +chown :nvm ${NVM_DIR} +chmod g+s ${NVM_DIR} +su ${USERNAME} -c "$(cat << EOF + set -e + umask 0002 + # Do not update profile - we'll do this manually + export PROFILE=/dev/null + curl -so- https://raw.githubusercontent.com/nvm-sh/nvm/v${NVM_VERSION}/install.sh | bash + source ${NVM_DIR}/nvm.sh + if [ "${NODE_VERSION}" != "" ]; then + nvm alias default ${NODE_VERSION} + fi + nvm clear-cache +EOF +)" 2>&1 +# Update rc files +if [ "${UPDATE_RC}" = "true" ]; then +updaterc "$(cat < /dev/null 2>&1; then + to_install="${to_install} make" + fi + if ! type gcc > /dev/null 2>&1; then + to_install="${to_install} gcc" + fi + if ! type g++ > /dev/null 2>&1; then + to_install="${to_install} g++" + fi + if ! type python3 > /dev/null 2>&1; then + to_install="${to_install} python3-minimal" + fi + if [ ! -z "${to_install}" ]; then + apt_get_update_if_needed + apt-get -y install ${to_install} + fi +fi + +echo "Done!" diff --git a/containers/java-8/README.md b/containers/java-8/README.md index d7fdc0e75c..cc78d01e10 100644 --- a/containers/java-8/README.md +++ b/containers/java-8/README.md @@ -2,7 +2,7 @@ ## Summary -*Develop Java applications. Includes the JDK 8 (and 11) and Java extensions.* +*Develop Java applications. Includes the JDK 8 and Java extensions.* | Metadata | Value | |----------|-------| @@ -23,8 +23,6 @@ See **[history](history)** for information on the contents of published images. > **Note:** A version of this [definition for **newer JDKs**](../java) is also available! -This definition includes both JDK 8 and JDK 11 due to the fact that the VS Code Java extension requires JDK 11+. The needed `devcontainer.json` settings are present to enable you to work with projects targeting Java 8. - While this definition should work unmodified, you can select the version of Debian the container uses to run Java 8 by updating the `VARIANT` arg in the included `devcontainer.json` (and rebuilding if you've already created the container). ```json @@ -37,11 +35,11 @@ You can also directly reference pre-built versions of `.devcontainer/base.Docker You can decide how often you want updates by referencing a [semantic version](https://semver.org/) of each image. For example: -- `mcr.microsoft.com/vscode/devcontainers/java:0-8` (or `0-8-bullseye`, `0-8-buster` to pin to an OS version) -- `mcr.microsoft.com/vscode/devcontainers/java:0.203-8` (or `0.203-8-bullseye`, `0.203-8-buster` to pin to an OS version) -- `mcr.microsoft.com/vscode/devcontainers/java:0.203.0-8` (or `0.203.0-8-bullseye`, `0.203.0-8-buster` to pin to an OS version) +- `mcr.microsoft.com/vscode/devcontainers/java:1-8` (or `1-8-bullseye`, `1-8-buster` to pin to an OS version) +- `mcr.microsoft.com/vscode/devcontainers/java:1.0-8` (or `1.0-8-bullseye`, `1.0-8-buster` to pin to an OS version) +- `mcr.microsoft.com/vscode/devcontainers/java:1.0.0-8` (or `1.0.0-8-bullseye`, `1.0.0-8-buster` to pin to an OS version) -However, we only do security patching on the latest [non-breaking, in support](https://github.com/microsoft/vscode-dev-containers/issues/532) versions of images (e.g. `0-8`). You may want to run `apt-get update && apt-get upgrade` in your Dockerfile if you lock to a more specific version to at least pick up OS security updates. +However, we only do security patching on the latest [non-breaking, in support](https://github.com/microsoft/vscode-dev-containers/issues/532) versions of images (e.g. `1-8`). You may want to run `apt-get update && apt-get upgrade` in your Dockerfile if you lock to a more specific version to at least pick up OS security updates. See [history](history) for information on the contents of each version and [here for a complete list of available tags](https://mcr.microsoft.com/v2/vscode/devcontainers/java/tags/list). diff --git a/containers/java-8/definition-manifest.json b/containers/java-8/definition-manifest.json index 5189e1eb9f..b36e656c8c 100644 --- a/containers/java-8/definition-manifest.json +++ b/containers/java-8/definition-manifest.json @@ -1,14 +1,9 @@ { "variants": [ "bullseye", "buster" ], - "definitionVersion": "0.205.3", + "definitionVersion": "1.0.0", "build": { "latest": false, "rootDistro": "debian", - "parent": "java", - "parentVariant": { - "bullseye": "11-bullseye", - "buster": "11-buster" - }, "architectures": { "bullseye": ["linux/amd64", "linux/arm64"], "buster": ["linux/amd64"] @@ -25,8 +20,8 @@ } }, "dependencies": { - "image": "mcr.microsoft.com/vscode/devcontainers/java:11-${VARIANT}", - "imageLink": "https://hub.docker.com/_/openjdk", + "image": "buildpack-deps:${BASE_IMAGE_VERSION_CODENAME}-curl", + "imageLink": "https://hub.docker.com/_/buildpack-deps", "apt": [{ "cgIgnore": false, "name": "yarn" diff --git a/containers/java-postgres/.devcontainer/devcontainer.json b/containers/java-postgres/.devcontainer/devcontainer.json index e0272c38b3..e3134230ad 100644 --- a/containers/java-postgres/.devcontainer/devcontainer.json +++ b/containers/java-postgres/.devcontainer/devcontainer.json @@ -10,7 +10,6 @@ "vscode": { // Set *default* container specific settings.json values on container create. "settings": { - "java.home": "/docker-java-home" }, // Add the IDs of extensions you want installed when the container is created. diff --git a/containers/java/.devcontainer/devcontainer.json b/containers/java/.devcontainer/devcontainer.json index d4518409c6..1401138739 100644 --- a/containers/java/.devcontainer/devcontainer.json +++ b/containers/java/.devcontainer/devcontainer.json @@ -20,7 +20,6 @@ "vscode": { // Set *default* container specific settings.json values on container create. "settings": { - "java.home": "/docker-java-home" }, // Add the IDs of extensions you want installed when the container is created. diff --git a/devcontainer-collection.json b/devcontainer-collection.json index 602038c39d..89b94fcfe5 100644 --- a/devcontainer-collection.json +++ b/devcontainer-collection.json @@ -1785,7 +1785,6 @@ "PATH": "${SDKMAN_DIR}/bin:${SDKMAN_DIR}/candidates/java/current/bin:${PATH}" }, "settings": { - "java.home": "/extension-java-home", "java.import.gradle.java.home": "/usr/local/sdkman/candidates/java/current" }, "include": [ diff --git a/script-library/container-features/src/devcontainer-features.json b/script-library/container-features/src/devcontainer-features.json index c88896fa1f..4b69ec8710 100644 --- a/script-library/container-features/src/devcontainer-features.json +++ b/script-library/container-features/src/devcontainer-features.json @@ -849,7 +849,6 @@ "PATH": "${SDKMAN_DIR}/bin:${SDKMAN_DIR}/candidates/java/current/bin:${PATH}" }, "settings": { - "java.home": "/extension-java-home", "java.import.gradle.java.home": "/usr/local/sdkman/candidates/java/current" }, "include": [