As anyone familiar with Python is abundantly aware, there are no shortage of package managers available for use. So, given that it wasn't going to be reasonable to bundle them all into a single Cloud Container image, we made a call to pick out some of the more popular options:
You might have your own favourite that we've omitted. We appreciate everyone's got their own preferences, however we've only included package managers that we have been able to test and get consistent results with. Feel free to let us know if we've missed a good one, though.
We've also made the system interpreter (Python 3.12) a little more cleanly integrated and bundled in the virtualenv
package, so if you just want Python up and running, it's there.
Users of the Python + Miniconda image, our first foray into providing a Python CC image, might notice that this is not compatible with your existing image. You'll need to create a new container in order to use the new image.
The Python Container is a service container. In order to create one, simply pick the 'SERVICE IMAGE' tab when creating a container and select the Python container image.
For the most part, using any of the bundled package managers will work exactly as the relevant documentation suggests. There are a few things to keep in mind though:
env
command while in an SSH session. The important thing to remember is that while you're welcome to change these, they're there to ensure that your environment is persistent in one of the Cloud Container mounts under /container
, or in a Container Volume.pymysql
expects the system to provide the MySQL client libraries. We've bundled a lot of commonly used packages, but if you find you're missing a dependency you've got a couple options:
UV is a fast and powerful package manager built by the team at Astral, who are also responsible for the popular Ruff project. UV supports both package management and Python environment management (meaning you can pick the Python version you run on).
UV will use /container/application/.uv
as a default management root.
Conda & Mamba are two sides of the same coin. Conda is the original, fully-fledged environment management solution, while Mamba is a faster, nearly feature-complete alternative.
Conda and Mamba will default to using /container/application/.conda
as a management root.
They both read from /opt/conda/.condarc
for more detailed configuration. Any changes to this file are not guaranteed to persist between container restarts.
Poetry is similar to UV, though a little more mature as a packaging solution. While it has experimental Python version management built into the bundled version, it's still not quite complete.
Poetry will by default use /container/application/.poetry
for its operations.
Pyenv is less of a package manager and more of an interpreter manager - it allows you to install the Python version you want, allowing you to spin up a virtualenv
against that version. Pyenv will install interpreters into /container/application/.pyenv
.
If you'd prefer to use the system interpreter, you'll also need to use virtualenv
and pip
to manage your packages. Make sure your environment is persisted somewhere in /container/application
or on a volume.
More likely than not, you're going to want Supervisor to take control of your process to ensure it's always running. A default template has been provided (commented out in /container/config/supervisor.conf
). How this is configured is somewhat dependent on the package manager you're using.
Both UV and Poetry are safe to run with their respective CLI tooling - i.e. uv run
or poetry run
. As long as Supervisor is configured to run in the correct project directory, your app should just run. For example, if you wanted to run a Litestar project that's based in /container/application/uv
, you'd use something like this:
[program:uv_app]
user=www-data
directory=/container/application/uv
autostart=true
autorestart=true
command=/bin/bash -c "uv run litestar --app main:app run --host 0.0.0.0 --port 8010"
stdout_logfile=/container/logs/supervisor/%(program_name)s-stdout.log
stderr_logfile=/container/logs/supervisor/%(program_name)s-stderr.log
Neither Mamba nor Conda are quite as well-suited to running in non-interactive environments, which means the conda run
and mamba run
commands won't play nice with Supervisor. The alternative here is to use a direct path to the binary you want to run. This is usually within your environment - for example, installing the same litestar
in a Conda environment, you can validate the path:
(condatest) python@ch-testserv:/container/application/conda$ which litestar
/container/application/.conda/envs/condatest/bin/litestar
You can then use that to run the litestar binary, which will respect the environment it's sourced from. The same works with Python:
(condatest) python@ch-testserv:/container/application/conda$ which python
/container/application/.conda/envs/condatest/bin/python
Those translate to Supervisor configs such as:
[program:conda_app]
user=www-data
directory=/container/application/conda
autostart=true
autorestart=true
command=/bin/bash -c "/container/application/.conda/envs/condatest/bin/litestar --app main:app run --host 0.0.0.0 --port 8012"
stdout_logfile=/container/logs/supervisor/%(program_name)s-stdout.log
stderr_logfile=/container/logs/supervisor/%(program_name)s-stderr.log
Similar to Mamba and Conda, Pyenv doesn't work quite so nicely when running in a non-interactive environment. While it's much more lightweight - in fact just running a glorified virtual environment that references the Python version you want - you'll still need to reference its path explicitly.
[program:pyenv_app]
user=www-data
directory=/container/application/pyenv
autostart=true
autorestart=true
command=/bin/bash -c "/container/application/.pyenv/versions/pyenvtest/bin/litestar --app app:app run --host 0.0.0.0 --port 8014"
stdout_logfile=/container/logs/supervisor/%(program_name)s-stdout.log
stderr_logfile=/container/logs/supervisor/%(program_name)s-stderr.log
If you're using the system environment (probably with virtualenv), you'll be able to directly reference the venv path. If this exists within your application directory (e.g. /container/application/.venv) you can reference it as a relative path:
[program:pyapp]
user=www-data
directory=/container/application/
autostart=true
autorestart=true
command=/bin/bash -c ".venv/bin/litestar --app app:app run --host 0.0.0.0"
stdout_logfile=/container/logs/supervisor/%(program_name)s-stdout.log
stderr_logfile=/container/logs/supervisor/%(program_name)s-stderr.log
Many applications need to run scheduled jobs - updating data, running mailers, etc. While you can incorporate these into Python apps using packages like APScheduler
, most Linux systems (our Cloud Container images included) come with Cron as a scheduler which is usually preferred. You can read more about using Cloud Container crontabs in our KB. Similar to using supervisorctl, unless you're using UV/Poetry, commands won't play nice in the non-interactive environment, so you may need to use explicit paths to binaries.
If you're looking to run a Python web application, you've got a couple options: