A Minimal Python Image with Dependencies
This page describes a starting point for a simple containerized Python deployment with a single script and single dependency (‘boto3’, but that's not important, any other would be included in the same way).
Following the recommendation of pythonspeed.com, I am starting FROM
python:3.7-slim-buster
.
The motivation for creating this is that I encountered a few Python-based Dockerfiles that ignored best practice and did other strange things,
from using Python 2.7 (in 2019), to installing dependencies with unknown versions, omitting a WORKDIR (a useful bit of
functional documentation) and creating needlessly large images. Often no care is taken over the order of creating layers,
which increases rebuild times. Oh, and prefer the simpler COPY
over ADD
for files.
I have avoided the above problems. If you see any different mistakes that I have successfully demonstrated, please let me know so I can fix them.
hello.py:
import boto3
print(f'Successfuly imported boto3 {boto3.__version__}')
requirements.txt:
#Only list required versions for direct dependencies,
#unless a conflict needs to be resolved.
boto3==1.9.248
Dockerfile:
FROM python:3.7-slim-buster
LABEL maintainer="r.luxury-yacht@exolete.com"
WORKDIR /usr/workdir
COPY requirements.txt .
RUN pip3 install -r requirements.txt
COPY hello.py .
CMD ["python", "hello.py"]
With those three files in a single directory, build and execute the image to show that everything is working.
$ docker build -t minimalpython:1.0 .
[boring build log omitted]
$ docker run minimalpython:1.0
Successfully imported boto3 1.9.248
… or, if you have renounced daemons:
$ buildah bud -t minimalpython:1.0 .
[similar build log omitted]
$ podman run minimalpython:1.0
Successfully imported boto3 1.9.248
Footnote on timing
The official guidance suggests that: “if your build contains several layers, you can order them from the less frequently changed (to ensure the build cache is reusable) to the more frequently changed”
That's what the above does, so rebuilding the image after a change to the deployed script is quick. Changing the
Dockerfile to perform both COPYs at once (COPY requirements.txt hello.py ./
) inflates the build time, by
causing the requirements to be downloaded again needlessly. Timings obviously depend on the system, but the increase in
time to rebuild on my system is from 0.3±0.2s for the suggested version above, to 8.5s plus any network pauses for a
version that naively COPY
s both at once.
⁂