We have been using Poetry for version pinning of Lambda Functions. This time we are looking at how to use Poetry in building Docker Images while minimizing the size of the resulting image. As an example Python application, we take the Sanic OpenAPI Example. You can find the full final code for this example setup in our GitHub repository.
Since we are looking at building Docker Images, the only interesting place to look is the
Dockerfile (assuming you already have a Poetry-based project).
In an effort to reduce the size of the final image, we are using three build stages in the Dockerfile:
pythonstage is used just to provide a common basis for the
poetrystage installs Poetry, and uses it to install the Python application and its dependencies in a virtual environment.
runtimestage builds the final Docker Image by copying and configuring the virtual environment from the
FROM python:3-slim as python ENV PYTHONUNBUFFERED=true WORKDIR /app FROM python as poetry ENV POETRY_HOME=/opt/poetry ENV POETRY_VIRTUALENVS_IN_PROJECT=true ENV PATH="$POETRY_HOME/bin:$PATH" RUN python -c 'from urllib.request import urlopen; print(urlopen("https://install.python-poetry.org").read().decode())' | python - COPY . ./ RUN poetry install --no-interaction --no-ansi -vvv FROM python as runtime ENV PATH="/app/.venv/bin:$PATH" COPY --from=poetry /app /app EXPOSE 8000 CMD somerandomap
The goal of the multi-stage build strategy is to reduce the size of the final image. Below we show the size (and increase compared to the base (
python:3-slim) image) for the images.
python:3-slim117 MB (base image)
python117 MB (0 MB increase)
poetry194 MB (77 MB increase)
poetry(with application) 278 MB (161 MB increase)
runtime179 MB (62 MB increase)
runtime image has a size increase of 62 MB from the base image, compared to the increase of 161 MB for the image that contains both the application and poetry we are saving 99MB.
(Curiously, these numbers do not add up. If the application adds 62 MB and poetry adds 77 MB, we would expect the sum of these to add 139 MB while, in fact, it adds 161 MB… What would be taking the additional 22 MB?)