Hello Cloud Run with Python

1. Introduction

96d07289bb51daa7.png

Cloud Run is a managed compute platform that enables you to run stateless containers that are invocable via HTTP requests. It is built on the Knative open-source project, enabling portability of your workloads across platforms. Cloud Run is serverless: it abstracts away all infrastructure management, so you can focus on what matters most — building great applications.

The goal of this tutorial is to create a simple web application and deploy it to Cloud Run.

2. Setup and requirements

Self-paced environment setup

  1. Sign-in to the Google 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.

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • The Project name is the display name for this project's participants. It is a character string not used by Google APIs, and you can update it at any time.
  • The Project ID must be unique across all Google Cloud projects and is immutable (cannot be changed after it has been set). The Cloud Console auto-generates a unique string; usually you don't care what it is. In most codelabs, you'll need to reference the Project ID (and it is typically identified as PROJECT_ID), so if you don't like it, generate another random one, or, you can try your own and see if it's available. Then it's "frozen" after the project is created.
  • There is a third value, a Project Number which some APIs use. Learn more about all three of these values in the documentation.
  1. Next, you'll need to enable billing in the Cloud Console in order to use Cloud resources/APIs. Running through this codelab shouldn't cost much, if anything at all. To shut down resources so you don't incur billing beyond this tutorial, follow any "clean-up" instructions found at the end of the codelab. 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 853e55310c205094.png.

55efc1aaa7a4d3ad.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:

9c92662c6a846a5c.png

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

9f0e51b578fecce5.png

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
ACTIVE  ACCOUNT
*       <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

[core]
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 Artifact Registry, Cloud Build, and Cloud Run APIs:

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

This should produce a success message similar to this one:

Operation "operations/..." finished successfully.

Now, you're ready to start working and write your application...

4. Write the application

In this step, you'll build a simple Flask-based Python application responding to HTTP requests.

Working directory

Use Cloud Shell to create a working directory named helloworld-python and switch to it:

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

main.py

Using Cloud Shell Editor (click the Open Editor button) or your preferred command line editor (nano, vim, or emacs), create a file named main.py and paste the following code into it:

from flask import Flask, request

app = Flask(__name__)


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


if __name__ == "__main__":
    # Development only: run "python main.py" and open http://localhost:8080
    # When deploying to Cloud Run, a production-grade WSGI HTTP server,
    # such as Gunicorn, will serve the app.
    app.run(host="localhost", port=8080, debug=True)

This code creates a basic web service responding to HTTP GET requests with a friendly message.

requirements.txt

Add a file named requirements.txt to define the dependencies:

# https://pypi.org/project/flask
Flask==2.1.2

# https://pypi.org/project/gunicorn
gunicorn==20.1.0

Procfile

Finally, add a file named Procfile to specify how the application will be served:

web: gunicorn --bind :$PORT --workers 1 --threads 8 --timeout 0 main:app

Make sure all files are present under the working directory:

ls

This should list the following files:

main.py  Procfile  requirements.txt

Your application is ready to be deployed, but let's test it first...

5. Test the application

To test the application, create a virtual environment:

virtualenv venv

Activate the virtual environment:

source venv/bin/activate

Install the dependencies:

pip install -r requirements.txt

You should get a confirmation message like the following:

...
Successfully installed Flask ... gunicorn ...

Start the application:

python main.py

The logs show that you are in development mode:

 * Serving Flask app 'main' (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: on
 * Running on http://localhost:8080/ (Press CTRL+C to quit)
...

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

c42718133ccf1a0d.png

This should open a browser window showing the Hello World! message.

You can also open another Cloud Shell session (a new terminal tab) by clicking the + icon and sending a web request to the application running locally:

curl localhost:8080

You should receive the following answer:

Hello World!

When you're done, go back to the main Cloud Shell session and stop the python main.py command with CTRL+C.

Exit the virtual environment:

deactivate

Finally, remove the virtual environment directory:

rm -r venv/

Your application works as expected: let's deploy it...

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:

REGION="europe-west4"

Make sure you are still in the working directory:

ls

This should list the following files:

main.py  Procfile  requirements.txt

Deploy the application to Cloud Run:

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

The first time, you'll get a prompt to create an Artifact Registry repository. Tap Enter to validate:

Deploying from source requires an Artifact Registry Docker repository to store
built containers. A repository named [cloud-run-source-deploy] in region [REGION]
will be created.

Do you want to continue (Y/n)?

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

...
OK Building and deploying new service... Done.
  OK Creating Container Repository...
  OK Uploading sources...
  OK Building Container... Logs are available at ...
  OK Creating Revision... Initializing project for the current region.
  OK Routing traffic...
  OK Setting IAM Policy...
Done.
Service [SERVICE]... has been deployed and is serving 100 percent of traffic.
Service URL: https://SERVICE-PROJECTHASH-REGIONID.a.run.app

You can get the service URL with this command:

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

This should display something like the following:

https://helloworld-python-PROJECTHASH-REGIONID.a.run.app

You can now use your application by opening the service URL in a web browser:

c836b93e5601e2cf.gif

You can also call the application from Cloud Shell:

curl $SERVICE_URL?who=me

This should give you the expected greeting:

Hello me!

Congratulations! You have just deployed an application 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. Clean up

While Cloud Run does not charge when the service is not in use, you might still be charged for storing the container image in Artifact Registry. You can delete your repository or delete your Cloud project to avoid incurring charges. Deleting your Cloud project stops billing for all the resources used within that project.

To delete your container image repository:

gcloud artifacts repositories delete cloud-run-source-deploy \
  --location $REGION

To delete your Cloud Run service:

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

To delete your Google Cloud project,

  1. Retrieve your current project ID:
PROJECT_ID=$(gcloud config get-value core/project)
  1. Make sure this is the project you wish to delete:
echo $PROJECT_ID
  1. Delete the project:
gcloud projects delete $PROJECT_ID

8. What's next?

96d07289bb51daa7.png

Cloud Run codelabs to check out: