Build Python docker deployment images with pyenv and poetry
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:
- 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!)
- Avoid any need for external network access on the deployment machine
- 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:
- Use two-stage Dockerfile see e.g. this post
- Install pyenv, build a recent version
- Install poetry
- Transfer the package being deployed over as a git repository and checkout
- Use poetry to install the packages into a virtualenv
- 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:
- Optimum performance
- Recent features and security fixes
- 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