Lets take a closer look at using Zappa in a real-world development environment for a full-featured Django app deployed to an AWS Lambda function, with static assets loaded to S3 and served by Cloudfront.

Getting a Django app to run in Lambda is a game changer. Lambda gives you the luxury of abstracting away the minutia behind the computing power needed to serve your dynamic web site. Better still, operating system patches and security headaches become a thing of the past, and your monthly hosting costs will likely drop to nearly $zero. A command-line deployment tool named Zappa was created to do exactly that, provided that you’ve setup both your cloud environment and development environments according to the set of “norms” that are described in this article.

“Zappa makes it super easy to build and deploy server-less, event-driven Python applications on AWS Lambda + API Gateway.”

Body Calc is a Django app running in an AWS serverless architecture based on the following diagram. The complete source code for this app is available on Github at https://github.com/bodycalc/bodycalc.io. In contrast to blogosphere articles showcasing simple “Hello, World” apps, I wanted to evaluate Zappa on a project that leverages real-world technologies like Git, NPM, Pip, Pipeline, Environ, Yarn, Gulp, Webpack and Bower. The good news is that only one of these, Pipeline, is affected by deploying to a Lambda function. As of this publication I’ve successfully used Pipeline to compress CSS and Js files, and to compile Sass. But thus far I’ve been unable to implement “cache busting” strategies with Pipeline, so keep checking back on this article from time to time as I continue to trouble-shoot this last remaining pain point.

I. AWS Environment

The challenge of getting Django to work inside a Lambda function is mostly about finding a workable combination of services to take care of the miscellaneous stuff that Lambda cannot do. For example, Lambda functions are not public facing, so you have to find an alternative way to host a public-facing URL that provides users with access to your site. Lambda functions do not include a file system either, so you need to implement an alternative strategy for serving the static assets associated with your site. Lambda functions cannot persist data, so your SQL database has to reside elsewhere, and in a location where Lambda can gain access over port 3306. Finally, you need a reasonable way to manage the myriad set of permissions across the various cloud services that makeup your deployment environment; sufficient to enable you to deploy your code, but secure enough that you’re not running the risk of your account getting breached.

II. Development Environment Prerequisites

Read, “Enemy at the Gates”

My firsthand account of how hackers stole my AWS credentials
(approximately 5 minutes).

III. Django Development Environment

I initially had a lot of difficulty getting Zappa to work because of the locations of files and folders in my project. In my case, problems ranged from simple stuff like Zappa including my static assets when it uploaded everything to Zappa not being able to see certain Django files within my project. Take note of my “final” working structure on the right, as this might save you some time.

More generally, following are my commands to create this project and to run it locally in order to verify that it at least works in a development environment.

$ virtualenv .env  #create a new virtual environment named ".env"
$ source .env/bin/activate  #activate the new virtual environment
$ 
$ django-admin startproject app   # create a new project named app
$ cd app
$ python manage.py runserver  # to verify that django installed and initialized correctly
$ python manage.py startapp bmi   # create the BMI web app
$ pip install django mysqlclient zappa django-environ django-npm django-pipeline jsmin

Settings.py is modified so as to relocate things in a way that works for Zappa. You can review the file in its current state here: https://github.com/bodycalc/bodycalc.io/django/app/settings.py

IV. Zappa setup

Zappa is actually a simple, easy-to-use command line tool. Once I’d properly organized my project files I only ran into a couple of other setup challenges. The more opaque of these regards the information that is supposed to get gathered up during the zappa init process. In my case at least, the settings identifying the AWS Virtual Private Network (VPC) subnet id values didn’t get populated, and so I had to look these up and add the values to the zappa_settings.json file manually as per this illustration.

You can lookup these values by navigating to “VPC” from the main console of AWS. From there, look for “subdomains”. The values in the json file correspond to the “Subnet ID” values that you’ll see on that screen. There should be three subnets.

You can probably disregard the SecurityGroupIds value, unless you need access to AWS resource like for example, RDS, for your development environment. If you do need this then you can lookup your security id values by navigating to “EC2” from the main console of AWS and then choosing “Security Groups”.

The second problem regards security and the IAM profile that I created. Zappa needs admin-level access to each AWS resource in your deployment architecture, which frankly, is a LOT of access. Compounding matters, IAM security is granular, and the specific permissions that Zappa needs remain unclear as of this publication. I ultimately had to temporarily add “admin” privileges to my IAM user to get my site deployed initially. Afterwards, after a lot of tweaking, I was able to use the IAM profile that you can review here: https://github.com/bodycalc/bodycalc.io/aws-iam-policy.json

I’m including the next couple of screenshots in case you’re new to IAM and are unsure what you’re supposed to do with this file. The basic idea is that you create an IAM user with programatic access (ie it uses a public ID and a secret key), and then you create and assign an IAM security profile that is custom tailored to the permissions that Zappa needs to deploy your Django app to AWS.

My IAM policy in Github is a json file which you can paste into your IAM policy by clicking the “Edit Policy” button from this screen, and then afterwards clicking on the “JSON” viewer option.

I hope you found this helpful. Please help me improve this article by leaving a comment below. Thank you!