diff --git a/projects/rocprofiler-systems/README.md b/projects/rocprofiler-systems/README.md index 193fcd4b9e..8e81fb6a2a 100755 --- a/projects/rocprofiler-systems/README.md +++ b/projects/rocprofiler-systems/README.md @@ -148,6 +148,9 @@ cd docker ./build-docker.sh --help ``` +> [!NOTE] +> The `-m` argument can be used to show supported OS + ROCm combinations. + **Example:** To set up an Ubuntu 24.04 + ROCm 6.4 + Python 3.12 environment for building and testing, run the following commands: ```shell diff --git a/projects/rocprofiler-systems/docker/Dockerfile.opensuse b/projects/rocprofiler-systems/docker/Dockerfile.opensuse index 81edfb2dd8..9fee2eed9f 100644 --- a/projects/rocprofiler-systems/docker/Dockerfile.opensuse +++ b/projects/rocprofiler-systems/docker/Dockerfile.opensuse @@ -30,13 +30,18 @@ RUN zypper --non-interactive update -y && \ ARG ROCM_VERSION=0.0 -RUN if [ "${ROCM_VERSION}" != "0.0" ]; then \ +RUN ROCM_MAJOR=$(echo "${ROCM_VERSION}" | sed 's/\./ /g' | awk '{print $1}') && \ + ROCM_MINOR=$(echo "${ROCM_VERSION}" | sed 's/\./ /g' | awk '{print $2}') && \ + if [ "${ROCM_MAJOR}" != "0" ] || [ "${ROCM_MINOR}" != "0" ]; then \ OS_VERSION=$(grep '^VERSION_ID=' /etc/os-release | cut -d'=' -f2 | tr -d '"') && \ OS_VERSION_MAJOR=$(echo "$OS_VERSION" | cut -d'.' -f1) && \ OS_VERSION_MINOR=$(echo "$OS_VERSION" | cut -d'.' -f2) && \ - ROCM_MAJOR=$(echo "${ROCM_VERSION}" | sed 's/\./ /g' | awk '{print $1}') && \ - ROCM_MINOR=$(echo "${ROCM_VERSION}" | sed 's/\./ /g' | awk '{print $2}') && \ - ROCM_VERSN=$(( ("${ROCM_MAJOR}"*10000)+("${ROCM_MINOR}"*100) )) && \ + ROCM_PATCH=$(echo "${ROCM_VERSION}" | sed 's/\./ /g' | awk '{print $3}') && \ + if [ -z "${ROCM_PATCH}" ] || [ "${ROCM_PATCH}" = "0" ]; then \ + ROCM_PATCH=0 && \ + ROCM_VERSION=$(echo "${ROCM_VERSION}" | sed 's/\.0$//') \ + ; fi && \ + ROCM_VERSN=$(( ("${ROCM_MAJOR}"*10000)+("${ROCM_MINOR}"*100) + ("${ROCM_PATCH}"))) && \ zypper --non-interactive addrepo https://download.opensuse.org/repositories/devel:languages:perl/15.6/devel:languages:perl.repo && \ zypper --non-interactive --no-gpg-checks install -y https://repo.radeon.com/amdgpu-install/${ROCM_VERSION}/sle/${OS_VERSION}/amdgpu-install-${ROCM_MAJOR}.${ROCM_MINOR}.${ROCM_VERSN}-1.noarch.rpm && \ zypper --non-interactive --gpg-auto-import-keys refresh && \ diff --git a/projects/rocprofiler-systems/docker/Dockerfile.rhel b/projects/rocprofiler-systems/docker/Dockerfile.rhel index acc5c9c2ff..ee237a8b60 100644 --- a/projects/rocprofiler-systems/docker/Dockerfile.rhel +++ b/projects/rocprofiler-systems/docker/Dockerfile.rhel @@ -23,13 +23,18 @@ RUN yum groupinstall -y "Development Tools" && \ ARG ROCM_VERSION=0.0 -RUN if [ "${ROCM_VERSION}" != "0.0" ]; then \ +RUN ROCM_MAJOR=$(echo "${ROCM_VERSION}" | sed 's/\./ /g' | awk '{print $1}') && \ + ROCM_MINOR=$(echo "${ROCM_VERSION}" | sed 's/\./ /g' | awk '{print $2}') && \ + if [ "${ROCM_MAJOR}" != "0" ] || [ "${ROCM_MINOR}" != "0" ]; then \ OS_VERSION=$(grep '^VERSION_ID=' /etc/os-release | cut -d'=' -f2 | tr -d '"') && \ OS_VERSION_MAJOR=$(echo "$OS_VERSION" | cut -d'.' -f1) && \ RPM_TAG=".el${OS_VERSION_MAJOR}" && \ - ROCM_MAJOR=$(echo "${ROCM_VERSION}" | sed 's/\./ /g' | awk '{print $1}') && \ - ROCM_MINOR=$(echo "${ROCM_VERSION}" | sed 's/\./ /g' | awk '{print $2}') && \ - ROCM_VERSN=$(( ("${ROCM_MAJOR}"*10000)+("${ROCM_MINOR}"*100) )) && \ + ROCM_PATCH=$(echo "${ROCM_VERSION}" | sed 's/\./ /g' | awk '{print $3}') && \ + if [ -z "${ROCM_PATCH}" ] || [ "${ROCM_PATCH}" = "0" ]; then \ + ROCM_PATCH=0 && \ + ROCM_VERSION=$(echo "${ROCM_VERSION}" | sed 's/\.0$//') \ + ; fi && \ + ROCM_VERSN=$(( ("${ROCM_MAJOR}"*10000)+("${ROCM_MINOR}"*100) + ("${ROCM_PATCH}"))) && \ if [ "${OS_VERSION_MAJOR}" -eq 8 ]; then PERL_REPO=powertools; else PERL_REPO=crb; fi && \ dnf -y --enablerepo=${PERL_REPO} install perl-File-BaseDir && \ yum install -y https://repo.radeon.com/amdgpu-install/${ROCM_VERSION}/rhel/${OS_VERSION}/amdgpu-install-${ROCM_MAJOR}.${ROCM_MINOR}.${ROCM_VERSN}-1${RPM_TAG}.noarch.rpm && \ diff --git a/projects/rocprofiler-systems/docker/Dockerfile.ubuntu b/projects/rocprofiler-systems/docker/Dockerfile.ubuntu index dab6dea85a..f8cfb64315 100644 --- a/projects/rocprofiler-systems/docker/Dockerfile.ubuntu +++ b/projects/rocprofiler-systems/docker/Dockerfile.ubuntu @@ -31,12 +31,17 @@ RUN apt-get update && \ python3 -m pip install 'cmake==3.21'; \ fi -RUN if [ "${ROCM_VERSION}" != "0.0" ]; then \ +RUN ROCM_MAJOR=$(echo "${ROCM_VERSION}" | sed 's/\./ /g' | awk '{print $1}') && \ + ROCM_MINOR=$(echo "${ROCM_VERSION}" | sed 's/\./ /g' | awk '{print $2}') && \ + if [ "${ROCM_MAJOR}" != "0" ] || [ "${ROCM_MINOR}" != "0" ]; then \ OS_VERSION=$(grep '^VERSION_ID=' /etc/os-release | cut -d'=' -f2 | tr -d '"') && \ OS_CODENAME=$(grep '^VERSION_CODENAME=' /etc/os-release | cut -d'=' -f2) && \ - ROCM_MAJOR=$(echo "${ROCM_VERSION}" | sed 's/\./ /g' | awk '{print $1}') && \ - ROCM_MINOR=$(echo "${ROCM_VERSION}" | sed 's/\./ /g' | awk '{print $2}') && \ - ROCM_VERSN=$(( ("${ROCM_MAJOR}"*10000)+("${ROCM_MINOR}"*100) )) && \ + ROCM_PATCH=$(echo "${ROCM_VERSION}" | sed 's/\./ /g' | awk '{print $3}') && \ + if [ -z "${ROCM_PATCH}" ] || [ "${ROCM_PATCH}" = "0" ]; then \ + ROCM_PATCH=0 && \ + ROCM_VERSION=$(echo "${ROCM_VERSION}" | sed 's/\.0$//') \ + ; fi && \ + ROCM_VERSN=$(( ("${ROCM_MAJOR}"*10000)+("${ROCM_MINOR}"*100) + ("${ROCM_PATCH}"))) && \ AMDGPU_DEB="amdgpu-install_${ROCM_MAJOR}.${ROCM_MINOR}.${ROCM_VERSN}-1_all.deb" && \ wget https://repo.radeon.com/amdgpu-install/${ROCM_VERSION}/ubuntu/${OS_CODENAME}/${AMDGPU_DEB} && \ apt-get install -y ./${AMDGPU_DEB} && \ diff --git a/projects/rocprofiler-systems/docker/build-docker.sh b/projects/rocprofiler-systems/docker/build-docker.sh index 39d22c58b4..c0b172118b 100755 --- a/projects/rocprofiler-systems/docker/build-docker.sh +++ b/projects/rocprofiler-systems/docker/build-docker.sh @@ -1,17 +1,163 @@ #!/usr/bin/env bash -: ${USER:=$(whoami)} -: ${ROCM_VERSIONS:="6.2"} -: ${DISTRO:=ubuntu} -: ${VERSIONS:=20.04} -: ${PYTHON_VERSIONS:="6 7 8 9 10 11 12 13"} -: ${BUILD_CI:=""} -: ${PUSH:=0} -: ${PULL:=--pull} -: ${RETRY:=3} +set-user-defaults() +{ + : ${USER:=$(whoami)} + : ${ROCM_VERSIONS:="6.3"} + : ${DISTRO:=ubuntu} + : ${VERSIONS:=20.04} + : ${PYTHON_VERSIONS:="6 7 8 9 10 11 12 13"} + : ${BUILD_CI:=""} + : ${PUSH:=0} + : ${PULL:=--pull} + : ${RETRY:=3} + : ${SCRIPT_DIR=$(dirname "$(readlink -f "${BASH_SOURCE[0]:-$0}")")} +} + +set-user-defaults set -e +cd $(dirname ${SCRIPT_DIR}) + +declare -a MATRIX_DISTROS=() +declare -a MATRIX_VERSIONS=() +declare -a MATRIX_ROCM_VERSIONS=() + +load-matrix() +{ + local workflow_file=".github/workflows/containers.yml" + if [ ! -f "${workflow_file}" ]; then + echo -e "\n Error: Cannot find ${workflow_file}" + exit 1 + fi + + # In form os-distro;os-version;rocm-version + local matrix_data=$(awk ' + /rocprofiler-systems-release:/, /steps:/ { + if (/- os-distro:/) { + gsub(/[[:space:]]*- os-distro:[[:space:]]*"/, "") + gsub(/"/, "") + distro = $0 + } + if (/os-version:/) { + gsub(/[[:space:]]*os-version:[[:space:]]*"/, "") + gsub(/"/, "") + version = $0 + } + if (/rocm-version:/) { + gsub(/[[:space:]]*rocm-version:[[:space:]]*"/, "") + gsub(/"/, "") + rocm = $0 + printf "%s;%s;%s\n", distro, version, rocm + } + } + ' "${workflow_file}") + + while IFS=';' read -r os_distro os_version rocm_version; do + MATRIX_DISTROS+=("$os_distro") + MATRIX_VERSIONS+=("$os_version") + MATRIX_ROCM_VERSIONS+=("$rocm_version") + done <<< "$matrix_data" +} + +validate-distro() +{ + local distro="${1}" + + if [ -n "${distro}" ]; then + distro=$(tolower "${distro}") + case "${distro}" in + ubuntu|opensuse|rhel) + ;; + *) + send-error "Unsupported distribution '${distro}'" "Supported distributions: ubuntu, opensuse, rhel" + ;; + esac + fi +} + +show-matrix() +{ + local filter_distro="${1:-}" + + if [ -n "${filter_distro}" ]; then + validate-distro "${filter_distro}" + filter_distro=$(tolower "${filter_distro}") + fi + + echo "" + if [ -n "${filter_distro}" ]; then + echo " Supported ${filter_distro} + ROCm Combinations " + echo " ==============================================" + else + echo " Supported OS + ROCm Combinations " + echo " ==========================================" + fi + echo "" + echo " OS Distribution Version ROCm Version" + echo " ---------------- ------- ------------" + + for i in "${!MATRIX_DISTROS[@]}"; do + if [[ -z "${filter_distro}" || "${MATRIX_DISTROS[i]}" == "${filter_distro}" ]]; then + printf " %-16s %-9s %s\n" "${MATRIX_DISTROS[i]}" "${MATRIX_VERSIONS[i]}" "${MATRIX_ROCM_VERSIONS[i]}" + fi + done + + echo "" + echo "ROCm '0.0' means no ROCm installation (CPU-only build)" + echo "" + echo "Note: Patch versions are also supported (See: https://repo.radeon.com/amdgpu-install/)" + echo "" +} + +# Cross checks arguments against compatibility matrix (ignores ROCm patch version) +validate-combinations() +{ + # Check OS version combinations + for VERSION in ${VERSIONS}; do + VERSION_MAJOR=$(echo ${VERSION} | sed 's/\./ /g' | awk '{print $1}') + VERSION_MINOR=$(echo ${VERSION} | sed 's/\./ /g' | awk '{print $2}') + + local os_version_valid=0 + for i in "${!MATRIX_DISTROS[@]}"; do + if [[ "${MATRIX_DISTROS[i]}" == "${DISTRO}" && \ + "${MATRIX_VERSIONS[i]}" == "${VERSION}" ]]; then + os_version_valid=1 + break + fi + done + + if [ ${os_version_valid} -eq 0 ]; then + send-error "Unsupported OS version :: ${VERSION}. See compatibility matrix for supported versions." + fi + done + + # Check ROCm version combinations + for VERSION in ${VERSIONS}; do + for ROCM_VERSION in ${ROCM_VERSIONS}; do + local valid=0 + ROCM_MAJOR=$(echo ${ROCM_VERSION} | sed 's/\./ /g' | awk '{print $1}') + ROCM_MINOR=$(echo ${ROCM_VERSION} | sed 's/\./ /g' | awk '{print $2}') + ROCM_MAJOR_MINOR="${ROCM_MAJOR}.${ROCM_MINOR}" + if ! ([ "${ROCM_MAJOR_MINOR}" == "0.0" ] && [ "${ROCM_VERSION}" != "0.0" ]); then + for i in "${!MATRIX_DISTROS[@]}"; do + if [[ "${MATRIX_DISTROS[i]}" == "${DISTRO}" && \ + "${MATRIX_VERSIONS[i]}" == "${VERSION}" && \ + "${MATRIX_ROCM_VERSIONS[i]}" == "${ROCM_MAJOR_MINOR}" ]]; then + valid=1 + break + fi + done + fi + + if [ ${valid} -eq 0 ]; then + send-error "Unsupported combination :: ${DISTRO}-${VERSION} + ROCm ${ROCM_VERSION}. See compatibility matrix for supported versions." + fi + done + done +} + tolower() { echo "$@" | awk -F '\\|~\\|' '{print tolower($1)}'; @@ -24,16 +170,18 @@ toupper() usage() { + set-user-defaults print_option() { printf " --%-20s %-24s %s\n" "${1}" "${2}" "${3}"; } echo "Options:" - print_option "help -h" "" "This message" - print_option "no-pull" "" "Do not pull down most recent base container" + print_option "help -h" "" "This message" + print_option "no-pull" "" "Do not pull down most recent base container" + print_option "matrix -m" "[ubuntu|opensuse|rhel]" "Shows compatibility matrix" echo "" print_default_option() { printf " --%-20s %-24s %s (default: %s)\n" "${1}" "${2}" "${3}" "$(tolower ${4})"; } print_default_option distro "[ubuntu|opensuse|rhel]" "OS distribution" "${DISTRO}" print_default_option versions "[VERSION] [VERSION...]" "Ubuntu, OpenSUSE, or RHEL release" "${VERSIONS}" - print_default_option rocm-versions "[VERSION] [VERSION...]" "ROCm versions" "${ROCM_VERSIONS}" + print_default_option rocm-versions "[VERSION] [VERSION...]" "ROCm versions (format: Major.Minor.Patch, patch defaults to 0 if not specified)" "${ROCM_VERSIONS}" print_default_option python-versions "[VERSION] [VERSION...]" "Python 3 minor releases" "${PYTHON_VERSIONS}" print_default_option "user -u" "[USERNAME]" "DockerHub username" "${USER}" print_default_option "retry -r" "[N]" "Number of attempts to build (to account for network errors)" "${RETRY}" @@ -84,7 +232,7 @@ reset-last() } reset-last - +load-matrix n=0 while [[ $# -gt 0 ]] do @@ -93,10 +241,19 @@ do usage exit 0 ;; + -m|--matrix) + shift + if [[ $# -gt 0 && ! "${1}" =~ ^-- ]]; then + show-matrix "${1}" + else + show-matrix + fi + exit 0 + ;; "--distro") shift - DISTRO=${1} - last() { DISTRO="${DISTRO} ${1}"; } + DISTRO=$(tolower ${1}) + last() { DISTRO="${DISTRO} $(tolower${1})"; } ;; "--versions") shift @@ -142,6 +299,10 @@ do shift done +# Validate input parameters for os-distros and rocm-versions +validate-distro +validate-combinations + DOCKER_FILE="Dockerfile.${DISTRO}" if [ "${RETRY}" -lt 1 ]; then @@ -149,7 +310,7 @@ if [ "${RETRY}" -lt 1 ]; then fi if [ -n "${BUILD_CI}" ]; then DOCKER_FILE="${DOCKER_FILE}.ci"; fi -if [ ! -f ${DOCKER_FILE} ]; then cd docker; fi +cd docker # Forced since PWD is parent dir if [ ! -f ${DOCKER_FILE} ]; then send-error "File \"${DOCKER_FILE}\" not found"; fi for VERSION in ${VERSIONS} @@ -159,93 +320,41 @@ do VERSION_PATCH=$(echo ${VERSION} | sed 's/\./ /g' | awk '{print $3}') for ROCM_VERSION in ${ROCM_VERSIONS} do - CONTAINER=${USER}/rocprofiler-systems:release-base-${DISTRO}-${VERSION}-rocm-${ROCM_VERSION} ROCM_MAJOR=$(echo ${ROCM_VERSION} | sed 's/\./ /g' | awk '{print $1}') ROCM_MINOR=$(echo ${ROCM_VERSION} | sed 's/\./ /g' | awk '{print $2}') ROCM_PATCH=$(echo ${ROCM_VERSION} | sed 's/\./ /g' | awk '{print $3}') - if [ -n "${ROCM_PATCH}" ]; then - ROCM_VERSN=$(( (${ROCM_MAJOR}*10000)+(${ROCM_MINOR}*100)+(${ROCM_PATCH}) )) - ROCM_SEP="." + if [ "${ROCM_PATCH}" = "0" ] || [ -z "${ROCM_PATCH}" ]; then + CONTAINER=${USER}/rocprofiler-systems:release-base-${DISTRO}-${VERSION}-rocm-${ROCM_MAJOR}.${ROCM_MINOR} else - ROCM_VERSN=$(( (${ROCM_MAJOR}*10000)+(${ROCM_MINOR}*100) )) - ROCM_SEP="" + CONTAINER=${USER}/rocprofiler-systems:release-base-${DISTRO}-${VERSION}-rocm-${ROCM_VERSION} fi if [ "${DISTRO}" = "ubuntu" ]; then - ROCM_REPO_DIST="ubuntu" - ROCM_REPO_VERSION=${ROCM_VERSION} - case "${ROCM_VERSION}" in - 6.*) - case "${VERSION}" in - 24.04) - ROCM_REPO_DIST="noble" - ;; - 22.04) - ROCM_REPO_DIST="jammy" - ;; - 20.04) - ROCM_REPO_DIST="focal" - ;; - *) - ;; - esac - ROCM_DEB=amdgpu-install_${ROCM_MAJOR}.${ROCM_MINOR}.${ROCM_VERSN}-1_all.deb + case "${VERSION}" in + 24.04) + ROCM_REPO_DIST="noble" + ;; + 22.04) + ROCM_REPO_DIST="jammy" + ;; + 20.04) + ROCM_REPO_DIST="focal" ;; *) ;; esac - verbose-build docker build . ${PULL} --progress plain -f ${DOCKER_FILE} --tag ${CONTAINER} --build-arg DISTRO=${DISTRO} --build-arg VERSION=${VERSION} --build-arg ROCM_VERSION=${ROCM_VERSION} --build-arg ROCM_REPO_VERSION=${ROCM_REPO_VERSION} --build-arg ROCM_REPO_DIST=${ROCM_REPO_DIST} --build-arg AMDGPU_DEB=${ROCM_DEB} --build-arg PYTHON_VERSIONS=\"${PYTHON_VERSIONS}\" + verbose-build docker build . ${PULL} --progress plain -f ${DOCKER_FILE} --tag ${CONTAINER} --build-arg DISTRO=${DISTRO} --build-arg VERSION=${VERSION} --build-arg ROCM_VERSION=${ROCM_VERSION} --build-arg PYTHON_VERSIONS=\"${PYTHON_VERSIONS}\" elif [ "${DISTRO}" = "rhel" ]; then - if [ -z "${VERSION_MINOR}" ]; then - send-error "Please provide a major and minor version of the OS. Supported: >= 8.8, <= 9.4" - fi - - # Components used to create the sub-URL below - # set in amdgpu-install//rhel/ - RPM_PATH=${VERSION_MAJOR}.${VERSION_MINOR} - RPM_TAG=".el${VERSION_MAJOR}" - - # set the sub-URL in https://repo.radeon.com/amdgpu-install/ - case "${ROCM_VERSION}" in - 6.*) - ROCM_RPM=${ROCM_VERSION}/rhel/${RPM_PATH}/amdgpu-install-${ROCM_MAJOR}.${ROCM_MINOR}.${ROCM_VERSN}-1${RPM_TAG}.noarch.rpm - ;; - 0.0) - ;; - *) - send-error "Unsupported combination :: ${DISTRO}-${VERSION} + ROCm ${ROCM_VERSION}" - ;; - esac - # use Rocky Linux as a base image for RHEL builds DISTRO_BASE_IMAGE=rockylinux/rockylinux - - verbose-build docker build . ${PULL} --progress plain -f ${DOCKER_FILE} --tag ${CONTAINER} --build-arg DISTRO=${DISTRO_BASE_IMAGE} --build-arg VERSION=${VERSION} --build-arg ROCM_VERSION=${ROCM_VERSION} --build-arg AMDGPU_RPM=${ROCM_RPM} --build-arg PYTHON_VERSIONS=\"${PYTHON_VERSIONS}\" + verbose-build docker build . ${PULL} --progress plain -f ${DOCKER_FILE} --tag ${CONTAINER} --build-arg DISTRO=${DISTRO_BASE_IMAGE} --build-arg VERSION=${VERSION} --build-arg ROCM_VERSION=${ROCM_VERSION} --build-arg PYTHON_VERSIONS=\"${PYTHON_VERSIONS}\" elif [ "${DISTRO}" = "opensuse" ]; then - case "${VERSION}" in - 15.*) - DISTRO_IMAGE="opensuse/leap" - echo "DISTRO_IMAGE: ${DISTRO_IMAGE}" - ;; - *) - send-error "Invalid opensuse version ${VERSION}. Supported: 15.x" - ;; - esac - case "${ROCM_VERSION}" in - 6.*) - ROCM_RPM=${ROCM_VERSION}/sle/${VERSION}/amdgpu-install-${ROCM_MAJOR}.${ROCM_MINOR}.${ROCM_VERSN}-1.noarch.rpm - ;; - 0.0) - ;; - *) - send-error "Unsupported combination :: ${DISTRO}-${VERSION} + ROCm ${ROCM_VERSION}" - ;; - esac + DISTRO_IMAGE="opensuse/leap" if [[ "${VERSION_MAJOR}" -le 15 && "${VERSION_MINOR}" -le 5 ]]; then PERL_REPO="15.6" else PERL_REPO="${VERSION_MAJOR}.${VERSION_MINOR}" fi - verbose-build docker build . ${PULL} --progress plain -f ${DOCKER_FILE} --tag ${CONTAINER} --build-arg DISTRO=${DISTRO_IMAGE} --build-arg VERSION=${VERSION} --build-arg ROCM_VERSION=${ROCM_VERSION} --build-arg AMDGPU_RPM=${ROCM_RPM} --build-arg PERL_REPO=${PERL_REPO} --build-arg PYTHON_VERSIONS=\"${PYTHON_VERSIONS}\" + verbose-build docker build . ${PULL} --progress plain -f ${DOCKER_FILE} --tag ${CONTAINER} --build-arg DISTRO=${DISTRO_IMAGE} --build-arg VERSION=${VERSION} --build-arg ROCM_VERSION=${ROCM_VERSION} --build-arg PERL_REPO=${PERL_REPO} --build-arg PYTHON_VERSIONS=\"${PYTHON_VERSIONS}\" fi if [ "${PUSH}" -ne 0 ]; then docker push ${CONTAINER}