The best Docker base image for your Python application (June 2023)
When you’re building a Docker image for your Python application, you’re building on top of an existing image—and there are many possible choices for the resulting container.
There are OS images like Ubuntu, and there are the many different variants of the
python base image.
Which one should you use? Which one is better? There are many choices, and it may not be obvious which is the best for your situation.
So to help you make a choice that fits your needs, in this article I’ll go through some of the relevant criteria, and suggest some reasonable defaults that will work for most people.
What is a base image?
Most Docker images aren’t built from scratch.
Instead, you take an existing image and use it as the basis for your image using the
FROM command in your Dockerfile:
Docker has a series of “official” Docker base images based on various Linux distributions, and also base images that package specific programming languages, in particular Python.
Note: Outside any specific best practice being demonstrated, the Dockerfiles in this article are not examples of best practices, since the added complexity would obscure the main point of the article.
Need to ship quickly, and don’t have time to figure out every detail on your own? Read the concise, action-oriented Python on Docker Production Handbook.
What do you want from a base image?
There are a number of common criteria for choosing a base image, though your particular situation might emphasize, add, or remove some of these:
- Stability: You want a build today to give you the same basic set of libraries, directory structure, and infrastructure as a build tomorrow, otherwise your application will randomly break.
- Security updates: You want the base image to be well-maintained, so that you get security updates for the base operating system in a timely manner.
- Up-to-date dependencies: Unless you’re building a very simple application, you will likely depend on operating system-installed libraries and applications (e.g. a compiler). You’d like them not to be too old.
- Extensive dependencies: For some applications less popular dependencies may be required—a base image with access to a large number of libraries makes this easier.
- Up-to-date Python: While this can be worked around by installing Python yourself, having an up-to-date Python available saves you some effort.
- Small images: All things being equal, it’s better to have a smaller Docker image than a bigger Docker image.
The need for stability suggests not using operating systems with limited support lifetime, like Fedora or non-LTS Ubuntu releases.
Why you shouldn’t use Alpine Linux
A common suggestion for people who want small images is to use Alpine Linux, but that can lead to longer build times, obscure bugs, and performance issues.
You can see the linked article for details, but I recommend against using Alpine.
Option #1: Ubuntu LTS, RedHat Universal Base Image, Debian
There are three major operating systems that roughly meet the above criteria: Debian Stable, Ubuntu LTS, and RedHat Enterprise Linux and clones. The latest versions:
|Debian “Bookworm” 12||2023||2028||
|RHEL 9||2022||2027||RedHat registry||3.11, 3.9|
Older versions, which you should avoid if possible:
|Debian “Bullseye” 11||2021||2025||
|RHEL 8||2019||2024||RedHat registry||3.9, 3.8|
- Previous versions of this article covered CentOS, but CentOS is no longer a long-term stable operating system. You can instead use other RHEL clones: OracleLinux, RockyLinux or Alma Linux.
- You can get long term security updates for older distributions, but that’s a bad idea; better to upgrade more often.
Option #2: The “official” Python Docker image
Another alternative is Docker’s own “official”
python image, which comes pre-installed with respective versions of Python (
3.11, etc.), and has multiple variants:
- Alpine Linux, which as I explained above I don’t recommend using.
- Debian “Bookworm” 12, with many common packages installed. The image itself is large, but the theory is that these packages are installed via common image layers that other official Docker images will use, so overall disk usage will be low.
- Debian “Bookworm” 12, with a
slimvariant. This lacks the common packages’ layers, and so the image itself is much smaller, but if you use many other “official” Docker images the overall disk usage will be somewhat higher.
For comparison purposes, the download size of
python:3.11-slim-bookworm is 51MB, and
python:3.11-alpine3.18 is 19MB.
Their uncompressed on-disk sizes are 149MB and 52MB respectively.
There are also versions based on older versions of Debian, “Bullseye” 11 and “Buster” 10.
Comparing the options
The “official” Docker image has the benefit of providing every version of Python you might want, and tends to be very up-to-date with bugfix releases. This is not necessarily the case with the long-term support distributions.
Focusing on point releases, at one point (September 2022), 3.9.14 has just been released less than two weeks previously; v3.9.12 was released in March 2022, six months before that. Here is what the different images provided at the time:
As you can see, Ubuntu and RedHat do a better but still rather lackluster job at staying up-to-date, but the “official” Docker image is the only one that actually includes the latest point release. You can however assume that all of them will include major security updates, at least.
I’ve written a separate article where I ran some benchmarks comparing multiple Python builds.
For Python 3.9, the choice of base image made a difference.
However, Python 3.10 includes some performance optimizations in the build by default, and shows no real difference between
For Python 3.10 and later, then, it likely doesn’t matter which option you choose.
Given the speed improvements in 3.11, more important than the base image is making sure you’re on an up-to-date release of Python.
- Debian 12 is the most up-to-date in terms of system packages and libraries, since it was released in June 2023.
- The “official” Docker
pythonimages are also based off Debian 12 if you use the default or
bookwormvariants, so they have the same benefit.
Ease of use and annoyances
- Both the
registry.access.redhat.com/ubi9/python-311images ship preconfigured with Python.
- With Debian and Ubuntu images, you need to add a couple of lines to your
Dockerfileto install Python—a minor inconvenience.
- If you’re using the system version of Python packaged with Debian 12, you can’t
pip installwithout creating a virtualenv.
So which should you use?
- If you’re a RedHat shop, you’ll want to use their image or one of their clones.
- If you want the absolute latest bugfix version of Python, or a wide variety of versions, the official Docker Python image is your best bet.
- If you want the absolute latest system packages, the official Docker Python image is still your best bet, since it’s based on Debian Bookworm, released June 2023. Once Ubuntu 24.04 comes out in April 2024, that will have the most up-to-date system packages.
Lacking specific constraints, I’d probably choose the official Docker Python image (
This will ensure you have access the latest Python bugfixes, and the latest system packages as well.
The concise and action-oriented guide to Docker packaging for production
Docker packaging for production is complicated, with as many as 70+ best practices to get right. And you want small images, fast builds, and your Python application running securely.
Take the fast path to learning best practices, by using the Python on Docker Production Handbook.
Free ebook: "Introduction to Dockerizing for Production"
Learn a step-by-step iterative DevOps packaging process in this free mini-ebook. You'll learn what to prioritize, the decisions you need to make, and the ongoing organizational processes you need to start.
Plus, you'll join over 7000 people getting weekly emails covering practical tools and techniques, from Docker packaging to Python best practices.