Python package management can be tricky because the default package manager (pip) doesn’t track dependency versions like npm does for Node.js.
That’s why you should use poetry
to manage Python packages. It creates a lock file, so you can be sure that the versions will be the same every time you reinstall.
However, this can be a challenge when you want to create a Docker image with poetry. You need to do an extra pip install poetry
(unless you include it in your base Python image). Also, using poetry to install packages can result in a larger Docker image size.
Dockerfiles
Here are the Dockerfiles I use to compare using poetry
and pip
:
Dockerfile.poetry
FROM python:3.12-slim
WORKDIR /app
# hadolint ignore=DL3013
RUN pip install --no-cache-dir poetry
COPY pyproject.toml .
COPY poetry.lock .
RUN poetry install --only main --no-root --no-directory
Dockerfile.pip
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt --no-cache-dir
Installed packages
requests = "^2.31.0"
polars = "^0.20.18"
fastapi = "^0.110.1"
pydantic = "^2.6.4"
python-dotenv = "^1.0.1"
langchain = "^0.1.14"
psycopg2-binary = "^2.9.9"
Result
The resulting image sizes are:
benchmark_poetry latest 23d3105ad0dd 11 seconds ago 520MB
benchmark_pip latest b7932a02a8d1 12 hours ago 388MB
As you can see, using poetry makes the image 132 MB
larger. If you deploy 12 times per month, that’s an extra 1584 MB
.
Even though storage is cheap these days, reducing image sizes can still be helpful! 😎