Deploy a Serverless RESTFUL API using Google Cloud Run and Cloud Firestore

Sandeep Pamidamarri
6 min readOct 2, 2020
Google Cloud Run Microservices for a Firestore Database

In this particular post, we will learn to deploy a highly-available, cost-effective Serverless RESTFUL API application using the Google Cloud Platform using Cloud Run and Cloud Firestore services.

The application is to serve the tech-bytes. Using the RESTFUL API, the consumers should be able to perform the CRUD (Create, Read, Update and Delete) operations.

Following technologies and systems are used:

  1. Python — Flask App: Webserver to serve the RESTFUL API
  2. Docker — Containerization of the App
  3. Google Cloud Run: Serverless Containerized Platform
  4. Google Cloud Firestore: Realtime No-SQL Serverless Database
  5. Postman: To test the deployed RESTFUL API

Set-up Firestore Database

Step 1: Create the Firestore database

Refer to the below Quickstart link on the Firestore database set-up

Step 2: Get the project firebase service account key JSON file

Navigate to the project in the firebase console and download the service account key in JSON.

Click on the project settings

Click on the service accounts and download the new private key

Step 2: Create documents in the Firestore database

Firestore is a realtime No-SQL database with a concept of a collection of documents.

Create a collection named tech-bytes and create a document tech-byte.

The sample looks like below:

Note: Not specific in the fields. Use your custom JSON Data model to store the Tech Byte

Develop a Python Flask Application

Step 1: Set-up Python project using PyCharm IDE

PyCharm is a useful IDE tool for Python project development.

Refer to the below website on the download instructions

Step 2: Create a new project using PyCharm

Create the new project [TechBytes] in PyCharm IDE.

Step 3: Install the Python packages

For this particular application, the following packages are used:

Refer to the below documentation on the package usage

Flask: A webserver package

Firebase-admin: This package is used to access the resources of the Firebase

Install the packages using pip command in the terminal window

pip install flask firebase-admin

Note: Create the requirements.txt with the above-required pip packages

Step 4: Develop the CRUD Operations

Place firebase service account key JSON file in the working directory

Copy the following code in the “app.py” file.

Note: Update the COLLECTION_NAME as created in the Firestore database. Verify the KEY.json file

# Required imports
import os
from flask import Flask, request, jsonify
from firebase_admin import credentials, firestore, initialize_app
#Initialize Flask app
app = Flask(__name__)
#Initialize Firestore DB
cred = credentials.Certificate('KEY.json')
default_app = initialize_app(cred)
db = firestore.client()
techbytes_ref = db.collection('COLLECTION_NAME')
@app.route('/add', methods=['POST'])
def create():
"""
create(): Add document to Firestore collection with request body.
Ensure you pass the custom ID as part of the JSON body in post request,
e.g. json={'id': 1, 'title': 'tech byte title'}
"""
try:
id = request.json['id']
techbytes_ref.document(id).set(request.json)
return jsonify({"success": True}), 200
except Exception as e:
return f"An Error Occurred: {e}"
@app.route('/list', methods=['GET'])
def read():
"""
read(): Fetches documents from Firestore collections as JSON.
techbytes: return document that matches query ID.
all_techbytes: Return all documents.
"""
try:
# Check if ID was passed to URL query
techbyte_id = request.args.get('id')
if techbyte_id:
techbyte = techbytes_ref.document(techbyte_id).get()
return jsonify(techbyte.to_dict()), 200
else:
all_techbytes = [doc.to_dict() for doc in techbytes_ref.stream()]
return jsonify(all_techbytes), 200
except Exception as e:
return f"An error Occured: {e}"
@app.route('/update', methods=['POST', 'PUT'])
def update():
""""
update(): Update document in Firestore collection with request body
Ensure you pass the custom ID as part of the JSON body in post request,
e.g. json={'id':'1', 'title':'Tech byte post'}
"""
try:
id = request.json['id']
techbytes_ref.document(id).update(request.json)
return jsonify({'success':True}), 200
except Exception as e:
return f"An Error Occurred: {e}"
@app.route('/delete', methods=['DELETE'])
def delete():
""""
delete(): Delete a document from the Firestore collection
Check for ID in the URL
"""
try:
id = request.args.get('id')
techbytes_ref.document(id).delete()
return jsonify({'success':True}), 200
except Exception as e:
return f"An Error Occurred: {e}"
port = int(os.environ.get('PORT', 8080))
if __name__ == '__main__':
app.run(threaded=True, host='0.0.0.0', port=port)

Dockerize the Application

Step 1: Create the docker file [Dockerfile]

Note: The commands have usage comments. Dockerfile will not have specific file extensions

# Dockerfile
FROM python:3.8-slim
# Python latest version docker image
RUN apt-get update -y
# Update the packages of the container
RUN apt-get install -y python-pip python-dev build-essential
# Install the required essentials in the container
COPY . /app
# Copy the current directory into the app folder in the container
WORKDIR /app
# Change the working directory to app folder
RUN pip install -r requirements.txt
# Install the requirements present in the requirements.txt file
ENTRYPOINT ["python"]
# Specify the entry point
CMD ["app.py"]
# Command file to execute

Step 2: Create the dockerignore file

Dockerignore file [.dockerignore] is useful to ignore the folder contents as part of the docker image

.git
Dockerfile
.DS_Store
.gitignore
.dockerignore

# PyCharm specific folder

.idea

# Environments
.env
.venv
env/
venv/
ENV/

Deploy to Google Cloud

Step 1: Create the “deploy.sh” file with the following commands

The first command is to create the container image in the Google Container Registry.

# build & push container image
gcloud builds submit --tag gcr.io/PROJECT_ID/techbytes-api

The second command is to create the Google Cloud Run service from the deployed Google Container Registry Image.

# build the cloud run from the container image
gcloud run deploy techbytes-api --image gcr.io/PROJECT_ID/techbytes-api --region REGION --platform managed --allow-unauthenticated

Step 2: Verify the deployed assets in the Google Cloud Console

Verify the image in the Google Container Registry

Verify the created service in the Google Cloud Run

Test the deployed RESTFUL API

Step 1: Click on the deployed cloud run service to get the endpoint URL

Step 2: Open the Postman to test the GET method

Note: Similarly, we can test the remaining methods of the deployed RESTFUL API

Congratulations, now you successfully deployed a highly-available, cost-effective RESTFUL API using the Serverless Google Cloud solutions that includes Cloud Run and Realtime database Cloud Firestore.

--

--

Sandeep Pamidamarri

Digital Transformation Leader | Pega Lead Solution Architect | Pega Certified Data Scientist | Pega Customer Service | Pega Sales Automation | AWS Cloud