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 <firstname.lastname@example.org>" 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
Need more help?
Services related to Python software packaging: https://bnikolic.co.uk/2023/05/22/python-ssc