Hello Cloud Run with Python

1. Introduction


Cloud Run is a managed compute platform that enables you to run stateless containers that are invocable via HTTP requests. Cloud Run is serverless: it abstracts away all infrastructure management, so you can focus on what matters most — building great applications.

It is built from Knative, letting you choose to run your containers either fully managed with Cloud Run, or in your Google Kubernetes Engine cluster with Cloud Run on GKE.

The goal of this tutorial is for you to build a container image and deploy it to Cloud Run.

2. Setup and requirements

Self-paced environment setup

  1. Sign in to Cloud Console and create a new project or reuse an existing one. (If you don't already have a Gmail or Google Workspace account, you must create one.)




Remember the project ID, a unique name across all Google Cloud projects (the name above has already been taken and will not work for you, sorry!). It will be referred to later in this codelab as PROJECT_ID.

  1. Next, you'll need to enable billing in Cloud Console in order to use Google Cloud resources.

Running through this codelab shouldn't cost much, if anything at all. Be sure to to follow any instructions in the "Cleaning up" section which advises you how to shut down resources so you don't incur billing beyond this tutorial. New users of Google Cloud are eligible for the $300 USD Free Trial program.

Start Cloud Shell

While Google Cloud can be operated remotely from your laptop, in this tutorial you will be using Cloud Shell, a command line environment running in the Cloud.

Activate Cloud Shell

  1. From the Cloud Console, click Activate Cloud Shell 4292cbf4971c9786.png.


If you've never started Cloud Shell before, you're presented with an intermediate screen (below the fold) describing what it is. If that's the case, click Continue (and you won't ever see it again). Here's what that one-time screen looks like:


It should only take a few moments to provision and connect to Cloud Shell.


This virtual machine is loaded with all the development tools you need. It offers a persistent 5GB home directory and runs in Google Cloud, greatly enhancing network performance and authentication. Much, if not all, of your work in this codelab can be done with simply a browser or your Chromebook.

Once connected to Cloud Shell, you should see that you are already authenticated and that the project is already set to your project ID.

  1. Run the following command in Cloud Shell to confirm that you are authenticated:
gcloud auth list

Command output

 Credentialed Accounts
*       <my_account>@<my_domain.com>

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. Run the following command in Cloud Shell to confirm that the gcloud command knows about your project:
gcloud config list project

Command output

project = <PROJECT_ID>

If it is not, you can set it with this command:

gcloud config set project <PROJECT_ID>

Command output

Updated property [core/project].

3. Enable the APIs

From Cloud Shell, enable the Cloud Build and Cloud Run APIs:

gcloud services enable cloudbuild.googleapis.com run.googleapis.com

This should produce a successful message similar to this one:

Operation "operations/acf.cc11852d-40af-47ad-9d59-477a12847c9e" finished successfully.

4. Write the sample application

You'll build a simple Flask-based Python application responding to HTTP requests.

To build your application, use Cloud Shell to create a new directory named helloworld-python and change directory into it:

mkdir ~/helloworld-python
cd ~/helloworld-python

Using one of your preferred command line editors (nano, vim, or emacs) or the Cloud Shell web editor (click on the "Open Editor" pen-shaped icon), create a file named app.py and paste the following code into it:


from flask import Flask, request

app = Flask(__name__)

@app.route("/", methods=["GET"])
def hello():
    """ Return a friendly HTTP greeting. """
    who = request.args.get("who", "World")
    return f"Hello {who}!\n"

if __name__ == "__main__":
    # Used when running locally only. When deploying to Cloud Run,
    # a webserver process such as Gunicorn will serve the app.
    app.run(host="localhost", port=8080, debug=True)

This code creates a basic web server responding to HTTP GET requests with a friendly message. Your app is now ready to be containerized, tested, and uploaded to Container Registry.

5. Containerize your app and upload it to Container Registry

To containerize the sample app, create a new file named Dockerfile in the same directory as the source files, and copy the following content:


# Use an official lightweight Python image.
# https://hub.docker.com/_/python
FROM python:3.9-slim

# Install production dependencies.
RUN pip install Flask gunicorn

# Copy local code to the container image.
COPY . .

# Service must listen to $PORT environment variable.
# This default value facilitates local development.

# Run the web service on container startup. Here we use the gunicorn
# webserver, with one worker process and 8 threads.
# For environments with multiple CPU cores, increase the number of workers
# to be equal to the cores available.
CMD exec gunicorn --bind$PORT --workers 1 --threads 8 --timeout 0 app:app

Define the PROJECT_ID and DOCKER_IMG environment variables which will be used throughout the next steps and make sure they have the correct values:

PROJECT_ID=$(gcloud config get-value project)


Now, build your container image using Cloud Build, by running the following command from the directory containing the Dockerfile:

gcloud builds submit --tag $DOCKER_IMG

Once pushed to the registry, you will see a SUCCESS message containing the image name. The image is stored in Container Registry and can be re-used if desired.

You can list all the container images associated with your current project using this command:

gcloud container images list

Before deploying, run and test the application locally from Cloud Shell, you can start it using these standard docker commands:

docker pull $DOCKER_IMG
docker run -p 8080:8080 $DOCKER_IMG

In the Cloud Shell window, click on the "Web preview" icon and select "Preview on port 8080":


This should open a browser window showing the "Hello World!" message. You can also simply use curl localhost:8080 from another Cloud Shell session. When you're done, you can stop your docker run command with ctrl+c.

6. Deploy to Cloud Run

Cloud Run is regional, which means the infrastructure that runs your Cloud Run services is located in a specific region and is managed by Google to be redundantly available across all the zones within that region. Define the region you'll use for your deployment, for example:


Deploy your containerized application to Cloud Run with the following command:

gcloud run deploy helloworld-python \
  --image $DOCKER_IMG \
  --platform managed \
  --region $REGION \
  • You can also define a default region with gcloud config set run/region $REGION.
  • The --allow-unauthenticated option makes the service publicly available. To avoid unauthenticated requests, use --no-allow-unauthenticated instead.

Then wait a few moments until the deployment is complete. On success, the command line displays the service URL:

Deploying container to Cloud Run service [helloworld-python] in project [PROJECT_ID...
✓ Deploying new service... Done.                                   
  ✓ Creating Revision... Revision deployment finished. Waiting for health check...
  ✓ Routing traffic...
  ✓ Setting IAM Policy...
Service [helloworld-python] revision [helloworld-python-...] has been deployed
and is serving 100 percent of traffic.
Service URL: https://helloworld-python-....a.run.app

You can also retrieve your service URL:

  gcloud run services describe helloworld-python \
  --platform managed \
  --region $REGION \
  --format "value(status.url)" \

This should display something like:


You can now visit your deployed container by opening the service URL in a web browser:


You can also call your service from Cloud Shell:

curl $SERVICE_URL?who=me

Congratulations! You have just deployed an application packaged in a container image to Cloud Run. Cloud Run automatically and horizontally scales your container image to handle the received requests, then scales down when demand decreases. You only pay for the CPU, memory, and networking consumed during request handling.

7. Time to clean up

While Cloud Run does not charge when the service is not in use, you might still be charged for storing the built container image.

You can either decide to delete your GCP project to avoid incurring charges, which will stop billing for all the resources used within that project, or simply delete your helloworld-python image using this command:

gcloud container images delete $DOCKER_IMG

To delete your Cloud Run service, use this command:

gcloud run services delete helloworld-python \
  --platform managed \
  --region $REGION

8. What's next?

Cloud Run codelabs to check out:

For more information on building a stateless HTTP container suitable for Cloud Run from code source and pushing it to Container Registry, see: