Pyenv is a nice tool for building and using a variety of Python versions on any Linux distribution. It allows, for example, using the latest Python version easily on stock Debian/Ubuntu/Redhat systems. Poetry is a modern tool for python dependency and packaging Python programs.

Here are some notes on building Docker deployment images with these tools. The reason for doing this:

  1. Have a fixed image for deployment which is known not to change and can be quickly deployed (Poetry can take a long time to resolve and install large Python collections of packages!)
  2. Avoid any need for external network access on the deployment machine
  3. Easy way to restrict permissions and contain the threat from untrusted Python packages

Alternative ways of doing this is for example use docker Python images, but for the purposes of this post I’m assuming it is desirable to use a O/S distribution standard image as the base.

Structure of the Dockerfile

The overall structure:

  1. Use two-stage Dockerfile see e.g. this post
  2. Install pyenv, build a recent version
  3. Install poetry
  4. Transfer the package being deployed over as a git repository and checkout
  5. Use poetry to install the packages into a virtualenv
  6. Copy over pyenv and the virtualenv to the deployment image

The sample Dockerfile

Here is the full file

FROM ubuntu:latest as compilesys

LABEL maintainer "Bojan Nikolic <bojan@bnikolic.co.uk>"

WORKDIR /
RUN apt-get update
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y \
        make \
        build-essential \
        libssl-dev \
        zlib1g-dev \
        libbz2-dev \
        libreadline-dev \
        libsqlite3-dev \
        wget \
        curl \
        llvm \
        libncurses5-dev \
        libncursesw5-dev \
        xz-utils \
        tk-dev \
        libffi-dev \
        liblzma-dev \
        git 

RUN git clone https://github.com/pyenv/pyenv.git /pyenv
ENV PYENV_ROOT /pyenv
RUN /pyenv/bin/pyenv install 3.10.10
RUN eval "$(/pyenv/bin/pyenv init -)" && /pyenv/bin/pyenv local 3.10.10 && pip install numpy poetry setuptools wheel six auditwheel

WORKDIR /
COPY .git myproject.git
RUN git clone myproject.git
WORKDIR /myproject

RUN mkdir -p .venv
RUN eval "$(/pyenv/bin/pyenv init -)" && /pyenv/bin/pyenv local 3.10.10 && poetry config virtualenvs.in-project true --local && poetry install

FROM ubuntu:latest as targetsys

COPY --from=compilesys /pyenv /pyenv
COPY --from=compilesys /myproject /myproject

Why?

Reasons for building Python using pyenv and using it in your applications:

  1. Optimum performance
  2. Recent features and security fixes
  3. Code provenance and security see also

On Windows

The project pyenv-win is similar in aims to pyenv but unlike pyenv it does not have the capability to compile the Python library and executables.

Need more help?

Services related to Python software packaging: https://bnikolic.co.uk/2023/05/22/python-ssc