Bringing Tokusatsu to AWS using Python flask, Zappa and Contentful

I am a massive fan of Tokusatsu. The genre contains a wide variety of shows such as kaiju monster movies like Godzilla, superhero TV serials such as Kamen Rider — along with Giant Robot Shows like Super Sentai.

One of the aspects of Tokusatsu that most appeals to me are the transformation sequences. If you've seen an episode of Power Rangers, you've seen one of these transformations. For the past 20 years, Power Rangers has been reusing footage from the Super Sentai series for their action scenes.

SuperSentai

When mentioning my passion for these transformations to my colleague and fellow developer evangelist Rouven Weßling, he suggested I channel my enthusiasm into building a small fan site. Never one to decline a challenge, I created a serverless Flask site in Python using Zappa — all powered by Contentful.

If you want to see my, website live then check out henshin.ruparel.co, or go straight to the code at GitHub.

In this blog post I’ll go through how to:

  • Build a simple python flask app
  • Use Contentful to manage, and create content
  • Deploy the web server on AWS lambda and returning a live URL through API Gateway

I’ll also highlight some of the costs and performance concerns when it comes to utilizing AWS lambda to manage your web server.

Why serverless is a good idea

Going serverless allows you to create and run applications and services without having to worry about servers - at least not servers that you have to maintain. You can leave provisioning, scaling, and managing servers to someone else. Best of all, when your code isn’t running, you’re not paying anything unlike traditional servers when your paying to maintain infrastructure.

Zappa is a fantastic Python library that makes it dead simple to deploy Python applications to AWS Lambda and Amazon API Gateway. With AWS Lambda, your application becomes completely serverless.

Combining Zappa, Flask, and Contentful enabled me to rapidly build a lightweight site that'll have negligible costs, require minimal time to update, and come with flexible scaling.

Getting started

To kick things off, we'll need to set up our Python environment together with our AWS configuration.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#Install virtualenv
$ pip install virtualenv

#Create a new virtualenv named env
$ virtualenv env

New python executable in /henshin/env/bin/python3.6
Also creating executable in /henshin/env/bin/python
Installing setuptools, pip, wheel...done.

#Activate the virtualenv
$ source env/bin/activate

#Install dependencies for the project
$ pip install Flask Zappa Contentful

In the code snippet above we’re taking the following steps:

  • Installing virtualenv
  • Using virtualenv we’ll create a new virtual environment and activate that virtual environment.
  • In the activated virtual environment, we’ll use pip to install our dependencies for the project.

It’s essential that we use virtual environment since Zappa will utilize it to create a package that’ll be uploaded and run on AWS Lambda.

Lastly, install and configure the AWS CLI if you haven't used it before.

Setting up the Contentful part

First, we're going to create a content model to track all the different shows.

Create a new content type

For our show we'll be adding the following field types:

  • Short text - Title of our show
  • Date & time - First air date
  • Date & time - Final air date
  • Short text - Type to track what the franchise the show is from
  • Media - To store the video transformation sequence. This is a single reference field. We'll be storing both the WebM and mp4 versions of this file to insure browser compatibility.
  • Media - For the second video file
  • Long text - A summary of the show
  • Short text - A URL to where we sourced the summary text from
  • Reference - To our separate character content model
  • Short Text - Our slug for building URLs

Which will look like so:

Content model layout

To finish our Contentful setup, we'll add our first content entry:

Creating a content entry

Building our Flask app

Now that we've taken care of the building our content model, creating our first show, and laying the groundwork with our virtualenv, we're ready to start writing our Python code.

1
2
3
4
5
6
7
8
9
10
from flask import Flask, render_template, url_for, abort
import contentful

client = contentful.Client(
    {Space ID},
    {Content Delivery API KEY})

app = Flask(__name__)

We'll start by importing all our dependences, connecting to Contentful and creating a Flask instance. You can find your Space ID and Content Delivery API key at via app.contentful.com -> Space Settings -> API keys. If you’ve skipped setting up a content model you can use my SPACE ID (mt0pmhki5db7) and Content Delivery API key (8c7dbd270cb98e83f9d8d57fb8a2ab7bac9d7501905fb013c69995ebf1b2a719) which are pre-configured for this example.

Next, we'll build the routing for our home page.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@app.route('/')
@app.route('/home')
def index():
    """index route. Gathers all shows from contentful and uses that to render page"""
    shows = client.entries(
        {'content_type': 'show',
         'order': 'fields.first_episode_date'})
    return render_template('index.html',
                           shows=shows,)

if __name__ == '__main__':
    app.run()

In this function, we reach out to Contentful to get the array of all our shows sorted by when they first aired. We then pass the shows to the built-in flask render function along with the following index.html template:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{% extends "layout.html" %}
{% block content %}
{% for show in shows %}
              <h1>{{ show.title }}</h1>
              <h2><strong>Original release:</strong> {{ show.first_episode_date   }}  - {{ show.last_episode_date}}</h2>
              <video controls>
                <source src="https:{{ show.henshin_webm.url() }}" type="video/webm" alt="{{show.title}}">
                <source src="https:{{ show.henshin_mp4.url() }}" type="video/mp4" alt="{{show.title}}">
                Your browser does not support video.
              </video>
{% endfor %}
{% endblock %}

With this flask can dynamically build a page containing all the shows. As we add entries into Contentful, our website will immediately update to include those entries as soon as we hit publish.

Now that we've got our flask app, let's get it deployed on AWS.

Deploying the Flask app to AWS with Zappa

Getting the python code onto the cloud is extremely simple. Since we've already installed Zappa in our virtual environment and configured AWS all we need to do to get rolling is to call 'zappa init'. This call will walk us through the creation of a configuration file.

Deploying the Flask app to AWS with Zappa

Next call 'zappa deploy,' and Zappa will package your application using your active virtual environment. The command will download lambda compatible versions of your python dependencies if needed. Once that’s taken care of your code will get uploaded into s3, deployed onto lambda, configured with API gateway and then return a URL that you'll be immediately able to access.

Amazon API gateway

If you head over to API Gateway, you'll see a new API containing your function.

Zappa update

When you want to update your code, all you need to do is call 'zappa update'.

Monitoring with Datadog

Evaluating performance and cost with Datadog

7 Shy Zappa Blog post image

I'm a big fan of using Datadog to keep an eye on my AWS account. Using their out of the box Lambda integration, I can quickly create and access dashboards to see the performance of my Lambda functions.

On average, it takes AWS Lambda and API Gateway about 30ms to render and return any of my pages — only 15ms of which are consumed by Contentful. Because of API Gateway a page view gets mapped directly to a function call.

Since AWS Lambda rounds up to the nearest 100ms and as I’m using the lowest available memory size, 128mb, for my function, I'll need to make 3,200,000 function calls a month before I exceed the Lambda free tier.

Even then, every additional function call that month will only cost a minuscule $0.000000208 or ~4,800,000 page views before I pay a cent. Additionally, API Gateway charges $3.50 per million API calls received — plus the cost of data transfer out, in gigabytes.

Something to note is that Zappa will schedule a regularly occurring CloudWatch event to keep the application warm and the responses in that 30ms range. By default, this is set to occur every 4 minutes. That means for every Zappa function you leave running you’ll be committing to about 10,000 function calls a month. Since I only leave my production instance running, that leaves me with plenty of additional calls before I have to move beyond the AWS Lambda free tier.

From this point, you can set up a custom domain and SSL certificate. Using these tools you'll be able to build a streamlined development and deployment process to quickly create and manage a serverless website. You can see some of the changes I've made to my fan site at henshin.ruparel.co and view the full source code at GitHub.

I want to hear from you

If this post helped you build something or you have questions I want to hear from you. Reach me at: Twitter: @ShyRuparel Email: Shy@Contentful.com GitHub: Shy

You can also head over to the Contentful Community and show off your creation in the Show & Tell section.

Blog posts in your inbox

Subscribe to receive most important updates. We send emails once a month.