diff --git a/2.7/Dockerfile b/2.7/Dockerfile index 6a2f054..24a3554 100644 --- a/2.7/Dockerfile +++ b/2.7/Dockerfile @@ -1,39 +1,25 @@ FROM praekeltfoundation/alpine-buildpack-deps:3.4 -# delete many traces of Alpine Python (so that they are not used by mistake) -# We can't just uninstall the Python package as we still want things that depend -# on it (e.g. libevent, pcre). We replace this Python with our version built -# from source. In the upstream Debian-based images, the package files are -# dpkg-divert'ed, but Alpine's package manager doesn't have this (obscure) -# functionality so instead we just delete the files. -RUN rm $(apk info -q --contents python) +# ensure local python is preferred over distribution python +ENV PATH /usr/local/bin:$PATH # http://bugs.python.org/issue19846 # > At the moment, setting "LANG=C" on a Linux system *fundamentally breaks Python 3*, and that's not OK. ENV LANG C.UTF-8 -# gpg: key 18ADD4FF: public key "Benjamin Peterson " imported ENV GPG_KEY C01E1CAD5EA2C4F0B8E3571504C367C218ADD4FF - ENV PYTHON_VERSION 2.7.12 # if this is called "PIP_VERSION", pip explodes with "ValueError: invalid truth value ''" ENV PYTHON_PIP_VERSION 8.1.2 RUN set -ex \ - && buildDeps=' \ + && apk add --no-cache --virtual .fetch-deps \ gnupg \ tar \ - tcl-dev \ - tk-dev \ - ' \ - && runDeps=' \ - tcl \ - tk \ - ' \ - && apk add --no-cache $runDeps $buildDeps \ - && curl -fSL "https://www.python.org/ftp/python/${PYTHON_VERSION%%[a-z]*}/Python-$PYTHON_VERSION.tar.xz" -o python.tar.xz \ - && curl -fSL "https://www.python.org/ftp/python/${PYTHON_VERSION%%[a-z]*}/Python-$PYTHON_VERSION.tar.xz.asc" -o python.tar.xz.asc \ + \ + && wget -O python.tar.xz "https://www.python.org/ftp/python/${PYTHON_VERSION%%[a-z]*}/Python-$PYTHON_VERSION.tar.xz" \ + && wget -O python.tar.xz.asc "https://www.python.org/ftp/python/${PYTHON_VERSION%%[a-z]*}/Python-$PYTHON_VERSION.tar.xz.asc" \ && export GNUPGHOME="$(mktemp -d)" \ && gpg --keyserver ha.pool.sks-keyservers.net --recv-keys "$GPG_KEY" \ && gpg --batch --verify python.tar.xz.asc python.tar.xz \ @@ -41,22 +27,43 @@ RUN set -ex \ && mkdir -p /usr/src/python \ && tar -xJC /usr/src/python --strip-components=1 -f python.tar.xz \ && rm python.tar.xz \ + \ + && apk add --no-cache --virtual .build-deps \ + gdbm-dev \ + tcl-dev \ + tk \ + tk-dev \ +# add build deps before removing fetch deps in case there's overlap + && apk del .fetch-deps \ + \ && cd /usr/src/python \ && ./configure \ --enable-shared \ --enable-unicode=ucs4 \ && make -j$(getconf _NPROCESSORS_ONLN) \ && make install \ - && curl -fSL 'https://bootstrap.pypa.io/get-pip.py' | python2 \ + \ + && wget -O /tmp/get-pip.py 'https://bootstrap.pypa.io/get-pip.py' \ + && python2 /tmp/get-pip.py "pip==$PYTHON_PIP_VERSION" \ + && rm /tmp/get-pip.py \ && pip install --no-cache-dir --upgrade pip==$PYTHON_PIP_VERSION \ - && [ "$(pip list | awk -F '[ ()]+' '$1 == "pip" { print $2; exit }')" = "$PYTHON_PIP_VERSION" ] \ + && [ "$(pip list |tac|tac| awk -F '[ ()]+' '$1 == "pip" { print $2; exit }')" = "$PYTHON_PIP_VERSION" ] \ + \ && find /usr/local -depth \ \( \ \( -type d -a -name test -o -name tests \) \ -o \ \( -type f -a -name '*.pyc' -o -name '*.pyo' \) \ \) -exec rm -rf '{}' + \ - && apk del $buildDeps \ + && runDeps="$( \ + scanelf --needed --nobanner --recursive /usr/local \ + | awk '{ gsub(/,/, "\nso:", $2); print "so:" $2 }' \ + | sort -u \ + | xargs -r apk info --installed \ + | sort -u \ + )" \ + && apk add --virtual .python-rundeps $runDeps \ + && apk del .build-deps \ && rm -rf /usr/src/python ~/.cache CMD ["python2"] diff --git a/3.5/Dockerfile b/3.5/Dockerfile index 4e0dcde..8e2728a 100644 --- a/3.5/Dockerfile +++ b/3.5/Dockerfile @@ -1,39 +1,25 @@ FROM praekeltfoundation/alpine-buildpack-deps:3.4 -# delete many traces of Alpine Python (so that they are not used by mistake) -# We can't just uninstall the Python package as we still want things that depend -# on it (e.g. libevent, pcre). We replace this Python with our version built -# from source. In the upstream Debian-based images, the package files are -# dpkg-divert'ed, but Alpine's package manager doesn't have this (obscure) -# functionality so instead we just delete the files. -RUN rm $(apk info -q --contents python) +# ensure local python is preferred over distribution python +ENV PATH /usr/local/bin:$PATH # http://bugs.python.org/issue19846 # > At the moment, setting "LANG=C" on a Linux system *fundamentally breaks Python 3*, and that's not OK. ENV LANG C.UTF-8 -# gpg: key F73C700D: public key "Larry Hastings " imported ENV GPG_KEY 97FC712E4C024BBEA48A61ED3A5CA953F73C700D - ENV PYTHON_VERSION 3.5.2 # if this is called "PIP_VERSION", pip explodes with "ValueError: invalid truth value ''" ENV PYTHON_PIP_VERSION 8.1.2 RUN set -ex \ - && buildDeps=' \ + && apk add --no-cache --virtual .fetch-deps \ gnupg \ tar \ - tcl-dev \ - tk-dev \ - ' \ - && runDeps=' \ - tcl \ - tk \ - ' \ - && apk add --no-cache $runDeps $buildDeps \ - && curl -fSL "https://www.python.org/ftp/python/${PYTHON_VERSION%%[a-z]*}/Python-$PYTHON_VERSION.tar.xz" -o python.tar.xz \ - && curl -fSL "https://www.python.org/ftp/python/${PYTHON_VERSION%%[a-z]*}/Python-$PYTHON_VERSION.tar.xz.asc" -o python.tar.xz.asc \ + \ + && wget -O python.tar.xz "https://www.python.org/ftp/python/${PYTHON_VERSION%%[a-z]*}/Python-$PYTHON_VERSION.tar.xz" \ + && wget -O python.tar.xz.asc "https://www.python.org/ftp/python/${PYTHON_VERSION%%[a-z]*}/Python-$PYTHON_VERSION.tar.xz.asc" \ && export GNUPGHOME="$(mktemp -d)" \ && gpg --keyserver ha.pool.sks-keyservers.net --recv-keys "$GPG_KEY" \ && gpg --batch --verify python.tar.xz.asc python.tar.xz \ @@ -41,26 +27,50 @@ RUN set -ex \ && mkdir -p /usr/src/python \ && tar -xJC /usr/src/python --strip-components=1 -f python.tar.xz \ && rm python.tar.xz \ + \ + && apk add --no-cache --virtual .build-deps \ + tcl-dev \ + tk \ + tk-dev \ +# add build deps before removing fetch deps in case there's overlap + && apk del .fetch-deps \ + \ && cd /usr/src/python \ && ./configure \ --enable-loadable-sqlite-extensions \ --enable-shared \ && make -j$(getconf _NPROCESSORS_ONLN) \ && make install \ - && pip3 install --no-cache-dir --upgrade pip==$PYTHON_PIP_VERSION \ - && [ "$(pip list | awk -F '[ ()]+' '$1 == "pip" { print $2; exit }')" = "$PYTHON_PIP_VERSION" ] \ + \ +# explicit path to "pip3" to ensure distribution-provided "pip3" cannot interfere + && if [ ! -e /usr/local/bin/pip3 ]; then : \ + && wget -O /tmp/get-pip.py 'https://bootstrap.pypa.io/get-pip.py' \ + && python3 /tmp/get-pip.py "pip==$PYTHON_PIP_VERSION" \ + && rm /tmp/get-pip.py \ + ; fi \ + && pip3 install --no-cache-dir --upgrade "pip==$PYTHON_PIP_VERSION" \ + && [ "$(pip list |tac|tac| awk -F '[ ()]+' '$1 == "pip" { print $2; exit }')" = "$PYTHON_PIP_VERSION" ] \ + \ && find /usr/local -depth \ \( \ \( -type d -a -name test -o -name tests \) \ -o \ \( -type f -a -name '*.pyc' -o -name '*.pyo' \) \ \) -exec rm -rf '{}' + \ - && apk del $buildDeps \ + && runDeps="$( \ + scanelf --needed --nobanner --recursive /usr/local \ + | awk '{ gsub(/,/, "\nso:", $2); print "so:" $2 }' \ + | sort -u \ + | xargs -r apk info --installed \ + | sort -u \ + )" \ + && apk add --virtual .python-rundeps $runDeps \ + && apk del .build-deps \ && rm -rf /usr/src/python ~/.cache # make some useful symlinks that are expected to exist RUN cd /usr/local/bin \ - && ln -s easy_install-3.5 easy_install \ + && { [ -e easy_install ] || ln -s easy_install-* easy_install; } \ && ln -s idle3 idle \ && ln -s pydoc3 pydoc \ && ln -s python3 python \ diff --git a/README.md b/README.md index 09c5303..8676008 100644 --- a/README.md +++ b/README.md @@ -9,5 +9,4 @@ These images are like the [official](https://hub.docker.com/_/python/) Python Do These images are *not* smaller than their Debian counterparts. They should be used to build Python software that includes native extensions. The software can then be used in smaller images by installing built [wheels](https://pypi.python.org/pypi/wheel). Good small base images for Python software are the `python:2-alpine` and `python:3-alpine` images. ## Caveats -* The [`dbm`](https://docs.python.org/2/library/dbm.html) module fails to build. The Alpine `db-dev` package doesn't seem to include the `dbm` symbols that Python wants. * The [`nis`](https://docs.python.org/2/library/nis.html) module isn't built. Alpine's libc does not include `nis` headers or libraries.