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.
Dockerfile
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:
- The
python
stage is used just to provide a common basis for thepoetry
andruntime
stages. - The
poetry
stage installs Poetry, and uses it to install the Python application and its dependencies in a virtual environment. - The
runtime
stage builds the final Docker Image by copying and configuring the virtual environment from thepoetry
stage.
Poetry and its dependencies are only installed in the poetry
stage and are not included in the final runtime
image. This approach is heavily inspired by this comment by Dylan Praul on GitHub.
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
Image Size
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-slim
117 MB (base image)python
117 MB (0 MB increase)poetry
194 MB (77 MB increase)poetry
(with application) 278 MB (161 MB increase)runtime
179 MB (62 MB increase)
The final 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?)