In this article, I'm going to show that deployment of the "Hello World" flask application with Zappa framework is really easy. Follow the steps and see for yourself.
Getting started
At the beginning, let’s assume that we have pure Python 3 installation. Firstly, let’s install virtualenv (zappa needs it), zappa and AWS Command Line Interface:
pip install virtualenv
pip install zappa
pip install awscli
Now, create dictionary and virtualenv for our project:
mkdir brave-zappa-tutorial
virtualenv brave-zappa
And activate the venv:
source brave-zappa/bin/activate
Flask App
It’s time to create our flask hello.py (minimal working example from flask tutorial):
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello, World!'
Let’s test the app and type in console:
export FLASK_APP=hello.py
flask run
When you visit website localhost:5000 in your browser, you will see “Hello World” from our application.
AWS Deployment
Now, we need to take step to deploy app on AWS Lambda. Firstly, set up your AWS credentials, run
aws configure
and follow the terminal wizard. As a result of execution this script, files under ~/.aws will be created. The next thing to do is creation of “zappa_settings.json” file. Command:
zappa init
will create initial setup. If it is necessary, you can add additional entries to this file i.e:
- aws_region
- roles entries (if role problem occurs, you’ ll have to set “manage_roles” to false and set “role_name”, “role_arn” by yourself.
And that’s it! Project is ready to deploy. Just you need to run (you need proper rights to manage stack):
zappa deploy
And project will be packet and send to the default stage. Zappa provides many additional functions, i.e:
- update - updates project on the server
- Rollback - rollbacks to a previous version
- Undeploy - removes the API Gateway and Lambda function
- Status - checks status of your deployment
- Tail - shows logs
And many more! Everything you’ll find on the zappa’s github page.
Bonus! Working with DynamoDB
The application described below is very simple, let’s make them more advanced and add support for DynamoDB. Let’s assume that we want to create table to store users of our service.
Setup local DynamoDB
If you want to test the database locally, you have to download them from: https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBLocal.html- A more detailed description is available in the this link.Unpack and run(jre 6.x or newer is required):
java -Djava.library.path=./DynamoDBLocal_lib -jar DynamoDBLocal.jar -sharedDb
User table creation
Now, let’s create basic table to keep the user data. We need to add:
app.config['DYNAMO_TABLES'] = [
dict(
TableName='users',
KeySchema=[dict(AttributeName='username', KeyType='HASH')],
AttributeDefinitions=[dict(AttributeName='username', AttributeType='S')],
ProvisionedThroughput=dict(ReadCapacityUnits=5,
WriteCapacityUnits=5)
)]
To our flask app. Let’s stop in this step for the moment and discuss the above code:
TableName it simply place for name of the table
KeySchema specifies the attributes that make up the primary key for a table
index.Of course, here you can place more than one key, but one
(and only one)must be HUSH.
KeyType the role that the key attribute will assume (HASH for partition
RANGE for sort key).
AttributeDefinitions
attributes that describe the key schama for the table and index. AttributeType can be S (String), N (number) or B (binary).
ProvisionedThroughput represents the throughput setting for a tableReadCapacityUnits
The maximum number of strongly consistent reads consumed per second before DynamoDB returns a ThrottlingException.
WriteCapacityUnits
The maximum number of writes consumed per second before DynamoDB returns a ThrottlingException
Full description available here: https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_CreateTable.html If you want to use local database, let’s set:
app.config['DYNAMO_ENABLE_LOCAL'] = True
app.config['DYNAMO_LOCAL_HOST'] = 'localhost'
app.config['DYNAMO_LOCAL_PORT'] = 8000
To use the table shema, you have to add:
dynamo = Dynamo()
dynamo.init_app(app)
To create table:
with app.app_context():
dynamo.create_all()
Additional views
We will create two simple views, that will take arguments from link and make some operations on the database:
create_user
@app.route('/put_user')
def create_user():
username = request.args.get('username')
first_name = request.args.get('first_name')
dynamo.tables['users'].put_item(Item={
'username': username,
'first_name': first_name,
})
return "User created"
put _item - creates new item or update old if exist.
get_user
@app.route('/get_user')
def get_user():
username = request.args.get('username')
response = dynamo.tables['users'].get_item(
Key={
'username': username,
}
)
try:
item = response['Item']
except KeyError:
return "Item not found"
return str(item)
get_Item - returns a set of attributes for the item with the given primary key. If there is no matching item, GetItem does not return any data and there will be no Item element in the response
Test and deploy
To test your app, run and visithttp://localhost:5000/put_user?username=john_doe&first_name=johnto create record: {username: john_doe, first_name:john} andhttp://localhost:5000/get_user?username=john_doe to get record from database
To update project on the AWS run:
zappa update
And voila! It works on the server!
Task for you
Taking data from the request link isn’t user friendly, so if you want to practice your flask and programing skills you can add some forms to project.