The best Docker base image for your Python application (February 2026)
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.
And now there’s a new choice, installing Python using uv, which allows you to use any base image you’d like.
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:
FROM debian:13
This base image may or may not include Python, so you may have to install it either from the Linux distribution, or some other way.
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 non-Python dependencies: In some cases you will depend on operating system-installed libraries and applications, for example a C compiler to compile an extension as part of the build. You’d like them not to be too old.
- Extensive non-Python 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 avoiding operating systems with limited support lifetime, like Fedora or non-LTS Ubuntu releases.
Why you probably 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; while the situation has improved since I first wrote it, I’d still personally not bother with 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:
| Distribution | Released | End-of-life | Image | Python versions |
|---|---|---|---|---|
| Ubuntu 24.04 | 2024 | 2029 | ubuntu:24.04 |
3.12 |
| Debian “Trixie” 13 | 2025 | 2028 | debian:13 |
3.13 |
| RHEL 10 | 2025 | 2030 | RedHat registry, or free clones like oracelinux:10, rockylinux:10, almalinux:10 |
3.12 |
Notes:
- Ubuntu 26.04 will be out in Q2 2026, likely with Python 3.13 and 3.14.
- RHEL 10 may add support for other Python versions in the future via the AppStream repository.
Older versions, which you probably don’t want to start with for a new project, include RHEL 9 and Debian 12, and as mentioned soon Ubuntu 24.04 will be superseded. You can get long term security updates for older distributions, but that’s a bad idea; better to upgrade more often. They may also not have security updates for all packages, as is the case for Debian long-term support.
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.10, 3.11, 3.12, etc.), and has multiple variants:
- Alpine Linux, which as I explained above I don’t recommend using.
- Debian “Trixie” 13, with many common packages installed.
The image itself is larger than the
slimvariant below, 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 “Trixie” 13, 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.14-slim-trixie is 41MB, and python:3.14-alpine3.23 is 17MB.
There are also versions based on older versions of Debian, like “Bookworm” 12. These are not worth using for new projects, and existing projects should upgrade.
Option #3: uv managed Python
The uv package installation and venv managed tool also supports downloading and installing a copy of Python when creating a virtualenv.
If you do this, you are not relying on a Docker image’s Python; you can use any base image you want.
Rather, the Python install comes from the Python Standalone Build project, so it will get installed via running uv in the Dockerfile.
For example:
$ uv venv --python=3.14 --managed-python ./myvenv
... automatic download happens here ...
Using CPython 3.14.2
Creating virtual environment at: ./myvenv
Activate with: source myvenv/bin/activate
Comparing the options
Python versions and patch releases
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.
The same is true for uv-based managed Python installs.
This is not necessarily the case with the long-term support distributions. Focusing on point releases, lets consider the status as of January 2026 for 3.12 and 3.13:
- 3.13: Latest point release is 3.13.11, from December 2025.
- 3.12: Latest point release is 3.12.12, from October 2025.
Here is what the different sources of Python provided:
| Image | Latest distro release | Patch release up-to-date? |
|---|---|---|
| Debian 13 | 3.13.5 | No, latest is 3.13.11 |
| Ubuntu 24.04 | 3.12.3 | No, latest is 3.12.12 |
| RHEL 10 | 3.12.12 | Yes |
Docker python |
3.13.11 | Yes |
uv managed Python |
3.13.11 | Yes |
So if you want the most up-to-date bug fixes for Python, the Docker python image uv managed are your best bet.
They also give you access to the latest major release of Python, unlike Linux distributions that only release every few years.
Security updates
The selling point Long-Term Support Linux distros is that they provide security updates. Even if they don’t ship the latest patch versions, they will backport all major security updates. However, they don’t do as good of a job keeping up with bug fixes from point releases, and may occasionally decide a very minor security issue isn’t worth backporting.
For system packages, the python:3.14 images defer to Debian.
For Python itself, they immediately ship patch releases.
uv currently has a manual process for catching security updates; they need to track both Python and dependent libraries like OpenSSL.
They do seem to be staying on top of these, and there’s a roadmap item to automate it.
Keep in mind that it’s critical that you use the latest version of the uv binary to ensure you get the latest security updates to Python.
So if you’re copying it from a Docker image, for example, you want to make sure that image isn’t an old cached version.
Performance
Depending how Python is compiled you can get different speeds, even for the same version. I’ve written a separate article where I ran some benchmarks comparing multiple Python builds.
In general the Ubuntu and uv builds seem to be 10-17% faster than the python Docker images provided by Docker, and are also faster than OracleLinux (the RHEL clone I tried).
System packages
- Ubuntu 24.04 is from 2024. However, the soon-to-be-released Ubuntu 26.04 will be the most up-to-date in terms of system packages and libraries.
- The “official” Docker
pythonimages are based off Debian 13, from 2025. - RHEL 10 is also from 2025.
For the most part all of these are fine.
So which should you use?
In previous versions of this article, my default suggestion was the official Docker Python image, e.g. python:3.14-slim-trixie.
But while that remains a fine choice, I now think uv’s managed Python may well be a better default choice, as it decouples choice of Linux distribution from the available Python version.
Using the uv managed Python, you can:
- Choose whichever base image you want. You’ll still want a Linux distribution with some stability and timely security updates, like Debian stable, Ubuntu LTS, or RHEL and its clones.
- Use any version of Python you want, along with the latest patch releases, including free-threaded builds.
- Get a faster Python build than many other Python distributions.
This does change how you build your Docker image, but not significantly.
You only need to install the latest version of uv, and then use it to create a virtualenv with a managed Python to get the benefit of its packaged Python.
You don’t have to change anything else about how you install or build code.
The one caveat is that they still don’t have an automated system to rebuild on security updates to dependencies, so if you are extra security conscious you might want to stick to the python:3.14 images for now.
