diff --git a/Dockerfile b/Dockerfile index 916534e..7bfa402 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,12 +1,22 @@ FROM ubuntu:14.04 -# Script to choose Python version -COPY choose_python.sh /usr/bin/ # Installer script for Pythons 2.7 3.4 3.5 3.6 COPY build_install_pythons.sh / -# Install Pythons 2.7 3.4 3.5 3.6 and matching pips -RUN bash build_install_pythons.sh && rm build_install_pythons.sh +# Install Pythons 2.7 3.4 3.5 3.6 3.3 2.6 and matching pips +RUN bash -c "source /build_install_pythons.sh && get_pythons_from_deadsnake" + +#Install Python 2.7.11 narrow, 3.7, 3.8.0rc1 +RUN bash -c "source /build_install_pythons.sh && install_build_dep" +RUN bash -c "source /build_install_pythons.sh && build_2_7_11_narrow" +RUN bash -c "source /build_install_pythons.sh && build_openssl 1.0.2o" +RUN bash -c "source /build_install_pythons.sh && compile_python 3.7.0 --with-openssl=/usr/local/ssl" +RUN bash -c "source /build_install_pythons.sh && compile_python 3.8.0 --with-openssl=/usr/local/ssl 3.8.0rc1" +# Post install and cleanup +RUN bash -c "source /build_install_pythons.sh && install_certificates" +RUN bash -c "source /build_install_pythons.sh && install_build_dep uninstall" + +RUN bash -c "rm build_install_pythons.sh" # Install manylinux1 libraries. See: # https://www.python.org/dev/peps/pep-0513/#the-manylinux1-policy @@ -16,5 +26,7 @@ RUN apt-get update && \ apt-get install -y libncurses5 libgcc1 libstdc++6 libc6 libx11-6 libxext6 \ libxrender1 libice6 libsm6 libgl1-mesa-glx libglib2.0-0 +# Script to choose Python version +COPY choose_python.sh /usr/bin/ # Run Python selection on way into image ENTRYPOINT ["/usr/bin/choose_python.sh"] diff --git a/README.rst b/README.rst index 00411c0..223e000 100644 --- a/README.rst +++ b/README.rst @@ -14,4 +14,6 @@ installed via ``apt-get install python2.7-dev`` (etc). Pip installed for each Python via `get-pip.py `_. +Pythons 3.7, 3.8rc1 are installed from source. They include pip and setuptools. + Dockerhub builds this image automatically on push to Github. diff --git a/build_install_pythons.sh b/build_install_pythons.sh index 8b3b5b4..f0d3ac6 100755 --- a/build_install_pythons.sh +++ b/build_install_pythons.sh @@ -1,43 +1,60 @@ #!/bin/bash -# Install Pythons 2.7 3.4 3.5 3.6 and matching pips -set -e +# Install Pythons 2.7 3.4 3.5 3.6 3.7 3.8rc1 and matching pips +set -ex -echo "deb http://ppa.launchpad.net/deadsnakes/ppa/ubuntu trusty main" > /etc/apt/sources.list.d/deadsnakes.list -apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 6A755776 -apt-get update -apt-get install -y wget -PIP_ROOT_URL="https://bootstrap.pypa.io" -wget $PIP_ROOT_URL/get-pip.py -for pyver in 3.4 3.5 3.6 2.7 2.6 3.3 ; do - pybin=python$pyver - apt-get install -y ${pybin}-dev ${pybin}-tk - get_pip_fname="get-pip.py" - for badver in 2.6 3.3 ; do - if [ "$pyver" == "$badver" ]; then - get_pip_fname="get-pip-${pyver}.py" - wget $PIP_ROOT_URL/${pyver}/get-pip.py -O $get_pip_fname - fi +function get_pythons_from_deadsnake { + echo "deb http://ppa.launchpad.net/deadsnakes/ppa/ubuntu trusty main" > /etc/apt/sources.list.d/deadsnakes.list + apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 6A755776 + apt-get update + apt-get install -y wget + PIP_ROOT_URL="https://bootstrap.pypa.io" + wget $PIP_ROOT_URL/get-pip.py + for pyver in 3.4 3.5 3.6 2.7 2.6 3.3 ; do + pybin=python$pyver + apt-get install -y ${pybin}-dev ${pybin}-tk + get_pip_fname="get-pip.py" + for badver in 2.6 3.3 ; do + if [ "$pyver" == "$badver" ]; then + get_pip_fname="get-pip-${pyver}.py" + wget $PIP_ROOT_URL/${pyver}/get-pip.py -O $get_pip_fname + fi + done + ${pybin} ${get_pip_fname} done - ${pybin} ${get_pip_fname} -done - -# Get virtualenv for Python 3.5 -pip3.5 install --user virtualenv +} -BUILD_PKGS="zlib1g-dev libbz2-dev libncurses5-dev libreadline-gplv2-dev \ - libsqlite3-dev libssl-dev libgdbm-dev tcl-dev tk-dev \ - libffi-dev liblzma-dev uuid-dev" -apt-get -y install build-essential $BUILD_PKGS +function install_build_dep { + BUILD_PKGS="zlib1g-dev libbz2-dev libncurses5-dev libreadline-gplv2-dev \ + libsqlite3-dev libssl-dev libgdbm-dev tcl-dev tk-dev \ + libffi-dev liblzma-dev uuid-dev" + if [ -z $1 ]; then + apt-get -y install build-essential $BUILD_PKGS + else + # Clean out not-needed packages + apt-get -y remove $BUILD_PKGS + apt-get -y autoremove + apt-get clean + # Remove stray files + rm -f get-pip*.py + fi +} function compile_python { - local py_ver="$1" + local py_dir="$1" + local py_ver="${3:-$1}" local extra_args="$2" local froot="Python-${py_ver}" local ftgz="${froot}.tgz" - wget https://www.python.org/ftp/python/${py_ver}/${ftgz} + wget https://www.python.org/ftp/python/${py_dir}/${ftgz} tar zxf ${ftgz} local py_nodot=$(echo ${py_ver} | awk -F "." '{ print $1$2 }') - local out_root=/opt/cp${py_nodot}m + local abi_suff=m + # Python 3.8 and up no longer uses the PYMALLOC 'm' suffix + # https://github.com/pypa/wheel/pull/303 + if [ ${py_nodot} -ge "38" ]; then + abi_suff="" + fi + local out_root=/opt/cp${py_nodot}${abi_suff} mkdir $out_root (cd Python-${py_ver} \ && ./configure --prefix=$out_root ${extra_args} \ @@ -47,15 +64,15 @@ function compile_python { rm -rf ${froot} ${ftgz} } -# Compile narrow unicode Python -# Compiled Pythons need to be flagged in the choose_python.sh script. -compile_python 2.7.11 "--enable-unicode=ucs2" -# Get pip for narrow unicode Python -/opt/cp27m/bin/python get-pip.py +function build_2_7_11_narrow { + # Compile narrow unicode Python + # Compiled Pythons need to be flagged in the choose_python.sh script. + compile_python 2.7.11 --enable-unicode=ucs2 + # Get pip for narrow unicode Python + /opt/cp27m/bin/python -mensurepip +} -# Compile Python 3.7.0, pip comes along with. -# Python 3.7 from deadsnakes does not appear to have SSL. -# Compilation needs SSL 1.0.2, not available for Trusty. +# Compilation of python 3.7+ needs SSL 1.0.2, not available for Trusty. function build_openssl { local version=$1 local froot="openssl-${version}" @@ -69,30 +86,22 @@ function build_openssl { rm -rf ${froot} ${ftgz} } -build_openssl 1.0.2o -# Compiled Pythons need to be flagged in the choose_python.sh script. -compile_python 3.7.0 "--with-openssl=/usr/local/ssl" - -# Install certificates from certifi, for Python 3.7 -# Thanks to Github user Mr BitBucket for this fix. -# Make virtuelenv for certifi install. -/root/.local/bin/virtualenv --python=/opt/cp37m/bin/python3 venv -. venv/bin/activate -# Install certifi and copy .pem file to system locaation. -pip install certifi -CERTIFI_CERT=$(python -c "import certifi; print(certifi.where())") -DEFAULT_CERT=$(python -c"import ssl; print(ssl.get_default_verify_paths().openssl_cafile)") -echo "CERTIFI_CERT=$CERTIFI_CERT" -echo "DEFAULT_CERT=$DEFAULT_CERT" -cp ${CERTIFI_CERT} ${DEFAULT_CERT} -deactivate -# Remove virtualenv files from image -rm -rf venv - -# Clean out not-needed packages -apt-get -y remove $BUILD_PKGS -apt-get -y autoremove -apt-get clean +function install_certificates { + # Install certificates from certifi, for Python 3.7+ + # Thanks to Github user Mr BitBucket for this fix. + # Make virtuelenv for certifi install. + pip3.5 install --user virtualenv + /root/.local/bin/virtualenv --python=/opt/cp37m/bin/python3 venv + . venv/bin/activate + # Install certifi and copy .pem file to system locaation. + pip install certifi + CERTIFI_CERT=$(python -c "import certifi; print(certifi.where())") + DEFAULT_CERT=$(python -c"import ssl; print(ssl.get_default_verify_paths().openssl_cafile)") + echo "CERTIFI_CERT=$CERTIFI_CERT" + echo "DEFAULT_CERT=$DEFAULT_CERT" + cp ${CERTIFI_CERT} ${DEFAULT_CERT} + deactivate + # Remove virtualenv files from image + rm -rf venv +} -# Remove stray files -rm -f get-pip*.py diff --git a/choose_python.sh b/choose_python.sh index 2e44d97..bbc6efa 100755 --- a/choose_python.sh +++ b/choose_python.sh @@ -3,14 +3,23 @@ # Then make a virtualenv from that Python and source it py_ver=${PYTHON_VERSION:-3.5} uc_width=${UNICODE_WIDTH:-32} +py_nodot=$(echo ${py_ver} | awk -F "." '{ print $1$2 }') if [ "$py_ver" == "2.7" ] && [ "$uc_width" == "16" ] \ - || [ "$py_ver" == "3.7" ]; then - py_nodot=$(echo ${py_ver} | awk -F "." '{ print $1$2 }') - py_bin=/opt/cp${py_nodot}m/bin/python$py_ver + || [ "$py_nodot" -ge "37" ]; then + local abi_suff=m + # Python 3.8 and up no longer uses the PYMALLOC 'm' suffix + # https://github.com/pypa/wheel/pull/303 + if [ ${py_nodot} -ge "38" ]; then + abi_suff="" + fi + py_bin=/oopt/cp${py_nodot}${abi_suff}/bin/python$py_ver else py_bin=/usr/bin/python$py_ver fi +if [ ! -e py_bin ]; then + exit 1 +fi /root/.local/bin/virtualenv --python=$py_bin venv source venv/bin/activate if [ "$py_ver" == "2.6" ]; then