Skip to content

Instantly share code, notes, and snippets.

@rwcitek
Last active February 19, 2023 01:37
Show Gist options
  • Save rwcitek/b02adc85bc449b16ad795b07723f747b to your computer and use it in GitHub Desktop.
Save rwcitek/b02adc85bc449b16ad795b07723f747b to your computer and use it in GitHub Desktop.
Compiling Python in a Docker image.

This is a collection of bash commands that builds a Python binary for a specific Linux environment using Docker. Environment variables are used to set default values, e.g. Python version and compile options. Using those environment variables, a HERE-DOC command creates a Dockerfile. Docker then uses the Dockerfile to build the Python binary within a Docker image.

To see what the latest Python version is, visit https://www.python.org/ftp/python/.

set environment variables ( optional )

Only if you want to use something different from the defaults.

# Base Docker image
py_FROM_IMAGE=ubuntu:22.04

# Python version
py_VER=3.12.0

# Python minor number
py_MINOR=a5

# Built Docker image name
py_TAG=python-builder-${py_FROM_IMAGE//[:.]/_}
py_REL=${py_VER}.${py_MINOR}

default and derived environment variables

py_FROM_IMAGE=${py_FROM_IMAGE:-$( source /etc/os-release  ; echo ${ID}:${VERSION_ID} )}
py_TAG="${py_TAG:-python-builder}"
py_REL="${py_REL:-latest}"

py_VER=${py_VER:-3.10.4}
py_PYVER="python-${py_VER}${py_MINOR}"
py_URI="https://www.python.org/ftp/python/${py_VER}/Python-${py_VER}${py_MINOR}.tar.xz"
py_CFGS=${py_CFGS:-"--enable-optimizations --prefix=/opt/${py_PYVER}"}

build Docker image

Create the Dockerfile

cat <<'eof' > Dockerfile
ARG FROM_IMAGE=debian:11
FROM ${FROM_IMAGE}

ARG VER
ARG MINOR
ARG URI
ARG CFGS

RUN DEBIAN_FRONTEND=noninteractive && \
    apt-get update && \
    apt-get install -y \
      build-essential \
      libffi-dev \
      libgdbm-dev \
      libncurses5-dev \
      libnss3-dev \
      libreadline-dev \
      libssl-dev \
      wget \
      xz-utils \
      zlib1g-dev \
    ;

WORKDIR /work
RUN   wget ${URI}
RUN   tar -x -J -f *.tar.xz

WORKDIR Python-${VER}${MINOR}/
RUN   ./configure ${CFGS}
RUN   make -j $(nproc) && make install

CMD /bin/bash
COPY Dockerfile /
eof

Build the image from the Dockerfile

docker build \
  --build-arg FROM_IMAGE="${py_FROM_IMAGE}" \
  --build-arg VER="${py_VER}" \
  --build-arg MINOR="${py_MINOR}" \
  --build-arg URI="${py_URI}" \
  --build-arg CFGS="${py_CFGS}" \
  -t ${py_TAG}:${py_REL} .

test within a container

docker container run --rm ${py_TAG}:${py_REL} /opt/${py_PYVER}/bin/python3 -V

create Docker instance and extract Python binary

docker container create --name python ${py_TAG}:${py_REL}
docker container cp python:/opt/python-${py_VER}${py_MINOR} .
docker container rm python
@edhowland
Copy link

Thanks. I'll grab the raw thing and try it out. On my Core i7 box, I only have the old 3.10 release we built sometime ago.
I understand there is significant performance gains in post 3.11.x+
This builds 3.12, so good to give it a try. Try to make time in the morning.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment