Running multiple versions of Python in Cloud Run
Tags: serverlessexpeditions, googlecloudrun, python
Published: 2020-12-11 01:05:06

On this episode of Serverless Expeditions, we take a look at how to deploy multiple versions of Python in Cloud Run.

Check out the video version of this blog post.

{% youtube -fbcOnrN-Eo %}

<figcaption>Running multiple versions of Python in Cloud Run - Serverless Expeditions (YouTube.com)<figcaption>

---

As new versions of Python are released, trying to choose between the new and shiny or the old and stable can be an issue. But if you are deploying on [Cloud Run](http://cloud.run/), you don't have to choose between the two, you can run both. 

Imagine this hypothetical scenario: you are an SRE for a company with a custom storefront, maintaining a fleet of virtual machines running various components, all with their own versions of Python. To improve reliability, you can upgrade all the components to use one version of Python, and move away from virtual machines, and into something more scalable, like serverless. 

This upgrade won't happen overnight, and the storefront must keep running in the meantime. So your plan is multi-step: migrate from virtual machines to serverless first, then make the language upgrades. But before migrating the existing systems, a new service coming online could be deployed serverless first, skipping the virtual machine all together. 

When choosing which serverless platform to upgrade to, limitations may exist on the languages available. For example, Cloud Functions only supports [specific versions of Python](https://cloud.google.com/functions/docs/concepts/python-runtime). 

However, the newest serverless offering from Google Cloud -- Cloud Run -- doesn't have this limitation. Cloud Run defines services as container images, which are defined by Dockerfiles, and can specify any base image. There is an entire repository of [official Python images on Docker Hub](https://hub.docker.com/_/python) which you can source from, by specifying the base image in the FROM line of your Dockerfile. 


```
FROM python:2.7
...
```



```
FROM python:3.9
...
```


As you migrate each service from its original virtual machine, you can set the exact version of Python it was originally running. You can also upgrade each service in isolation, as your team has time and resources. 

Once your dependencies have been upgraded and you want to test your service, you can deploy your new revision to only a limited number of users, using the [Traffic Splitting feature of Cloud Run.](https://cloud.google.com/run/docs/rollouts-rollbacks-traffic-migration#gradual) You can set your new revision to serve, say, only 5% of requests, so if there is something wrong, only some of your users are affected, and you can quickly rollback if there are any issues. 

By migrating each service in turn, you are able to control each service in isolation, allowing for a more incremental upgrade process, and a more reliable environment. 

By being able to specify the exact version of Python being used in your project, you can run multiple services each with their own isolated Python environment, which allows you more time to upgrade each service to supported versions of Python. 

It also allows you to try the newest versions of Python -- [such as prereleases of Python 3.10](https://hub.docker.com/_/python?tab=tags&page=1&name=3.10&ordering=last_updated) -- as soon as their images are available on Docker Hub.


## About Serverless Expeditions

Serverless Expeditions is a fun and cheeky video series that looks at what serverless means and how to build serverless apps with Google Cloud. 

Follow these hosts on Twitter at [@glasnt](https://twitter.com/glasnt) and [@martinomander](https://twitter.com/martinomander).