This article is a work in progress…

The Amazon Web Services (AWS) website has instructions for doing this, but they are mostly tailored to doing it on a Linux machine. Here’s how to do it on Windows 7.

Prerequisites

  • Download and unzip the Elastic Beanstalk command line tools package (eb)
  • TIP: Unzip it into a directory so that there are no spaces in the full filepath. Spaces + command line = not fun.

    Add eb to the path

    set PATH=%PATH%;C:\Users\andygilbertson\AWS-ElasticBeanstalk-CLI-2.6.0\eb\windows\
  • Python 2.7
  • Make sure Git is installed
  • Have virtualenv installed
  • To install with PIP, here’s the command:

    pip install http://pypi.python.org/packages/source/v/virtualenv/virtualenv-1.7.2.tar.gz

    Steps

    Open up a command prompt (cmd.exe, not PowerShell)

    Create a virtual environment

    cd C:\
    virtualenv --python=C:\Python27\python.exe Users\andygilbertson\envs\django_aws_hello
    NOTE: The second argument is optional. It is the version of Python you want the virtual environment to build.
    NOTE: The slashes are reversed from what the Amazon documentation has. The command won’t accept the second argument unless you reverse the directory slashes correctly.

    This will create a mini Python installation in the directory. You can go there and see the files to confirm.

    Go into the newly created “Scripts” directory

    cd C:\Users\andygilbertson\envs\django_aws_hello\Scripts

    Then activate the virtual environment

    activate
    NOTE: This is where you don’t want to be using PowerShell. VirtualEnv’s activate script is subject to execution policies on Windows. For some reason cmd.exe doesn’t have issues.

    Now you’ll see your virtual environment name in parentheses to indicate you are in your virtual environment
    Inside your virtual env, install django and python

    pip install django==1.6.2
    easy_install MySQL-python==1.2.5
    NOTE: Getting mysql-python to install correctly was way harder than it should have been. I think the problem is that on Windows this package has some Visual Basic dependencies (C compiler), as noted by the developer. Installing it via easy_install rather than pip solved the issue.

    Start the Django project locally

    cd..
    django-admin.py startproject hellodjango

    Go into the newly created root folder for your local Django site

    cd hellodjango

    Create the requirements.txt file

    pip freeze > requirements.txt

    After freezing, requirements.txt should look like this:

    Django==1.6.2
    mysql-python==1.2.5

    Initialize the Git repository

    git init .

    Make sure you’re in the project directory

    cd C:\Users\andygilbertson\envs\django_aws_hello\hellodjango

    Run eb init

    eb init

    Now you’ll have to fill in a bunch of Elastic Beanstalk settings.

    Here’s the link if you need fresh access keys

    Settings to choose

    • Environment Tier: WebServer::Standard::1.0
    • Solution stack: 32bit Amazon Linux 2013.09 running Python 2.7
    • Environment type: LoadBalanced
    • Create an RDS DB instance: y

     

    On your local computer, create an .ebextensions directory in the top-level directory of your source bundle. In this example, we use /root/mysite/.ebextensions.

    mkdir .ebextensions

    Create a configuration file (myapp.config)

    container_commands:
      01_syncdb:    
        command: "django-admin.py syncdb --noinput"
        leader_only: true
    
    option_settings:
      - namespace: aws:elasticbeanstalk:container:python
        option_name: WSGIPath
        value: mysite/wsgi.py
      - option_name: DJANGO_SETTINGS_MODULE
        value: mysite.settings
      - option_name: AWS_SECRET_KEY
        value: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
      - option_name: AWS_ACCESS_KEY_ID
        value: AKIAIOSFODNN7EXAMPLE
    
    NOTES:
    • Make sure you fill in all four of the option_settings with your data.
    • Make sure your config file doesn’t have tab characters. Use only spaces for indenting

    Save this .config file in the newly created .ebextensions directory

    Edit your settings.py file (/root/mysite/settings.py). Add this for the DATABASES object:

    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            'NAME': os.environ['RDS_DB_NAME'],
            'USER': os.environ['RDS_USERNAME'],
            'PASSWORD': os.environ['RDS_PASSWORD'],
            'HOST': os.environ['RDS_HOSTNAME'],
            'PORT': os.environ['RDS_PORT'],
        }
    }

    Add these files to the Git repository and commit the changes

    git add .
    git commit -m "eb configuration"
    git aws.push

    New you can run eb start to actually initialize Elastic Beanstalk with all the settings

    eb start

    When it’s all up and running (it takes about 15 minutes) you should be able to get some status info

    eb status --verbose

    When the server status is Green, you should be able to grab the supplied URL and plug it into your browser. If everything went according to plan, you’ll see Django’s basic welcome page.

    If you see the Elastic Beanstalk starter page (not Django’s), you may have to run Git aws.push again.

    git aws.push

    Troubleshooting

    One of the first places to look is the AWS Console. Go to Elastic Beanstalk, find your environment. On the left you’ll see “Logs”. “Snapshot Logs” and read through them to find errors.

    Closing Up Shop

    To stop the Elastic Beanstalk server/environment

    eb stop

    To delete the Elastic Beanstalk server/environment

    eb delete

    To deactivate your virtual environment

    cd C:\Users\andygilbertson\envs\django_aws_hello\Scripts
    deactivate

This post is just to document what worked for me to get a very basic implementation of a Flask API up and running with Amazon Web Services (AWS) Elastic Beanstalk. For this I was using Flask version 0.10.1.

The main Python code comes from this Flask tutorial.

 

Elastic Beanstalk set up

First create a new Elastic Beanstalk application in AWS dashboard.

Configuration Settings

Environment Type

  • Environment tier: Web Server
  • Predefined configuration: Python (2.7)
  • Environment type: Load balancing, autoscaling

Application Version

  • Application source: Sample application (for now)

Additional Resources

  • Create RDS DB instance? (not needed)
  • Create environment inside a VPC? (not needed)

Configuration Details

  • Instance type: t1.micro (free)
  • EC2 key pair: none for now

Go ahead and create the environment. It takes 5-10 to start it up.

After it starts you’ll see the URL of your sample application near the top of the dashboard (circled yellow). You can visit this link to verify the environment started up correctly.

URL to sample application
URL to sample application

 

application.py

Here is Python code for our basic API:

import flask

base_url = 'flaskapitest-env.elasticbeanstalk.com'

application = flask.Flask(__name__)

#Set application.debug=true to enable tracebacks on Beanstalk log output.
#Make sure to remove this line before deploying to production.
application.debug=True

tasks = [
    {
        'id': 1,
        'title': u'Buy groceries',
        'description': u'Milk, Cheese, Pizza, Fruit, Tylenol',
        'done': False
    },
    {
        'id': 2,
        'title': u'Learn Python',
        'description': u'Need to find a good Python tutorial on the web',
        'done': False
    }
]

@application.errorhandler(400)
def not_found(error):
    return flask.make_response(flask.jsonify( { 'error': 'Bad request' } ), 400)

@application.errorhandler(404)
def not_found(error):
    return flask.make_response(flask.jsonify( { 'error': 'Not found' } ), 404)

@application.route('/')
def hello_world():
    return "Hello world!"

@application.route('/todo/api/v1.0/tasks', methods = ['GET'])
def get_tasks():
    return flask.jsonify( { 'tasks': map(make_public_task, tasks) } )

def make_public_task(task):
    new_task = {}
    for field in task:
        if field == 'id':
            new_task['uri'] = base_url + '/todo/api/v1.0/task/' + str(task[field])
        else:
            new_task[field] = task[field]
    return new_task


if __name__ == '__main__':
    application.run(host='0.0.0.0', debug=True)

Make sure to replace the base_url variable to the URL to your application that was pointed out above.
Save this code as “application.py”

 

requirements.txt

You’ll also need a text file called requirements.txt. Save this file in the same directory as application.py.
The contents of requirements.txt (one liner):

Flask==0.10.1

 

Zip, Upload, Deploy

When both these files exist in the same folder, select and zip both of them into the same zip archive.

NOTE: Do not zip the folder itself, zip the files inside of the folder.

Now go into the Elastic Beanstalk dashboard and use the “Upload and Deploy” button to upload the zip archive.

After the dashboard comes up as green, we’re ready for a quick test.

 

Test with cURL

On Windows, open up a command line window. Make sure you have cURL installed and included in the path.

This command should return “Hello World!”:

curl -i http://testflaskapp-env.elasticbeanstalk.com

This command should return the short task list:

curl -i http://testflaskapp-env.elasticbeanstalk.com/todo/api/v1.0/tasks