I wanted to create a very small image for my Python applications, but it's difficult to do it from scratch because you cannot build a statically linked Python application so you need to include required libraries (e. g. glibc, libffi, etc.).
I looked at distroless project but then decided to build my own image based off busybox images. Busybox is very small but it's convenient to have some tools like sh, ls, df, etc. inside your image.
Here's the result: Winand/python-base-images. I copy Python installation from Python's official image, clean it, then copy certificates and some essential libraries.
The size is around 35.0MB for glibc version (python:3.12-slim is 123.6MB). and 31.3MB for musl version (python:3.12-alpine is 48.3MB).
Also I remove pip, so you need to mount uv tool to be able to install packages. This example uses pyproject.toml and uv.lock file but it can also install packages from requirements.txt.
FROM ghcr.io/astral-sh/uv:0.5.14 AS uv COPY pyproject.toml uv.lock / FROM python:3.12-musl # https://docs.astral.sh/uv/concepts/python-versions/#disabling-automatic-python-downloads ENV UV_PYTHON_DOWNLOADS=never # for uv sync https://docs.astral.sh/uv/concepts/projects/config/#project-environment-path ENV UV_PROJECT_ENVIRONMENT=/usr/local USER root RUN --mount=from=uv,source=/uv,target=/bin/uv \ --mount=from=uv,source=/pyproject.toml,target=/pyproject.toml \ --mount=from=uv,source=/uv.lock,target=/uv.lock \ # Install dependencies from an existing uv.lock uv sync --frozen --no-cache --no-dev --no-install-project USER app COPY --chown=app:app ./application /application