Deploying a Django App to AWS Elastic Beanstalk

Amazon Web Services offers a deployment tool enabling developers to focus on building great software and significantly reduces the role of managing servers, designing network architecture, configuring load balancing, application scaling and health monitoring.

Elastic Beanstalk is an easy-to-use service for deploying web applications/services developed with Java, .NET, PHP, Node.js, Python, Ruby, and Docker on well-known and real-world tested server architecture such as Apache, Nginx and Internet Information Server (IIS). Many other application platforms are also supported.

Developers only need to upload their code and Elastic Beanstalk automatically handles the deployment and service monitoring.

While this level of integration with AWS obfuscates the underlying server and network management, rest assured that you still have complete control over your AWS instances, EC2, RDBMS and much more.

Elastic Beanstalk automatically scales your application up and down based on your application's needs using adjustable Auto Scaling settings.

For example, you can use "CPU" utilization metrics to trigger Auto Scaling events and actions. With Elastic Beanstalk, your application can handle peaks in workload or website traffic while minimizing your costs.

You have complete freedom to select the AWS resources and Amazon EC2 instance types that are optimal for your application.

Additionally, Elastic Beanstalk lets you peak under the hood and retain full control over the AWS resources that power your application. If you decide you want to take over some (or all) of the elements of your infrastructure, you can do so seamlessly by using Elastic Beanstalk's management capabilities.

To get started using Elastic Beanstalk, download and install the EB CLI (awsebcli). This is the easiest way to deploy applications using EB. Once your code is ready, zip the application and the virtual environment in a single .war, .rar, or zip archive.

OK, let's get started...

Set up your virtual environment

Create a virtual environment named eb-django1

~$ virtualenv eb-django1

Activate the virtual environment:

~$ source ~/eb-django1/bin/activate
(eb-django1) ~$

You will see (eb-dango1) prepended to your command prompt, indicating that you've successfully activated your local development's virtual environment.

Next, use pip (Python Packaging) to install the latest version of Django by entering the following command:

(eb-django1)~$ pip install django==1.9.2

Once Django has been collected and installed int the virtual environment, verify the install by entering:

(eb-django1)~$ pip freeze
Django==1.9.2  
wheel==0.29.0  

This command lists all of the packages installed in your virtual environment. Later you will use the output of this command to configure your project for use with Elastic Beanstalk.

Alternatively, you can run Python and import django from the command line and check the version, like so...

(eb-django1)~$ which pip
/eb-django1/bin/pip
(eb-django1)~$ which python
/eb-django1/bin/python
(eb-django1)~$ python
Python 2.7.6 (default, Jun 22 205 17:58:13)  
[GCC 4.8.2] on linux
Type "help", "copyright", "credits" or "license" for more information.  
>>> import django
>>> django.get_version()
1.9.2  

Next, scaffold your Django application

First, activate your local development virtual environment:

~$ source ~/eb-django1/bin/activate

Use the django-admin startproject command to create a new Django project named eb-djangoproj:

(eb-django1)~$ django-admin startproject eb-djangoproj

This command creates a standard Django site named eb-djangoproj with the following directory structure:

~/eb-djangoproj
  |-- eb-djangoproj
  |   |-- __init__.py
  |   |-- settings.py
  |   |-- urls.py
  |   `-- wsgi.py
  `-- manage.py

Run your Django site locally with manage.py runserver:

(eb-virt) ~$ cd ebdjango
(eb-virt) ~/ebdjango$ python manage.py runserver 5000

Open http://127.0.0.1:5000/ in a web browser to view the site:

Configure Your Django Application for Elastic Beanstalk

Now that you have a Django-powered website on your local development machine, you can configure it for deployment to Elastic Beanstalk.

By default, Elastic Beanstalk looks for a file called application.py to start your application. Now, this doesn't exist in the Django project that we just created, therefore, we need to make a minor adjustment to the application's environment.

You will also need to set environment variables so that your application's modules can be loaded.

To configure your site for Elastic Beanstalk

Activate your virtual environment:

~/eb-djangoproj$ source ~/eb-django1/bin/activate

Next, run pip freeze and save the output to a file named requirements.txt:

(eb-django1) ~/eb-djangoproj$ pip freeze > requirements.txt

Elastic Beanstalk uses the requirements.txt file to determine which Python packages need to be installed on the EC2 instances that run your Elastic Beanstalk application.

Create a new directory, called .ebextensions:

(eb-django1) ~/eb-djangoproj$ mkdir .ebextensions

Within the .ebextensions directory, add a new configuration file named django.config with the following text:

Example ~/eb-djangoproj/.ebextensions/django.config

option_settings:  
  aws:elasticbeanstalk:container:python:
    WSGIPath: ebdjango/wsgi.py

WSGIPath specifies the location of the Web Server Gateway Interface (WSGI) script that EB uses to start your new application.

Deactivate your virtual environment by with the deactivate command:

(eb-django1) ~/eb-djangoproj$ deactivate

Reactivate your virtual environment whenever you need to add additional packages to your application or run your application locally.

Deploy Your Site With the EB CLI

Now that you have added all of the necessary application dependencies required to deploy your application on Elastic Beanstalk, your project directory should look like this:

~/eb-djangoproj/
|-- .ebextensions
|   `-- django.config
|-- eb-djangoproj
|   |-- __init__.py
|   |-- settings.py
|   |-- urls.py
|   `-- wsgi.py
|-- db.sqlite3
|-- manage.py
`-- requirements.txt

Next, we'll create the application environment and deploy our configured application with EB.

To create an environment and deploy your Django application, initialize your EB CLI repository with the eb init command:

~/eb-djangoproj$ eb init -p python2.7 django-tutorial

Application django-tutorial has been created.
This command creates a new application named django-tutorial and configures the local repository to create environments with the latest Python 2.7 platform configuration.

(optional) Run eb init again to configure a default key pair so that you can connect to the EC2 instance running your application with SSH:

~/eb-djangoproj$ eb init
Do you want to set up SSH for your instances?  
(y/n): y
Select a keypair.  
1) my-keypair  
2) [ Create new KeyPair ]  

Select a key pair if you have one already, or follow the prompts to create a new one. If you don't see the prompt or need to change your settings later, run eb init -i.

Create an environment and deploy you application to it with eb create:

~/eb-djangoproj$ eb create django-env

This command creates a load balanced Elastic Beanstalk environment named django-env. Creating an environment takes about 5 minutes. As Elastic Beanstalk creates the necessary server resources required to run your application, it outputs informational messages that the EB CLI and relays it to your terminal.

When the environment creation process completes, open your web site with eb open:

~/eb-djangoproj$ eb open

This will open a browser window using the domain name created for your application. You should see the same Django website that you created and tested locally.

If you do see your application running, then congratulations, you've deployed your first Django application with Elastic Beanstalk!

Updating Your Application

Now that you have a running application on Elastic Beanstalk, you can update and redeploy your application or its configuration and Elastic Beanstalk will take care of the work of updating your instances and starting your new application version.

For this example, we'll enable Django's admin console and configure a few other settings.

Modify Your Site Settings

By default, your Django web site uses the UTC time zone to display time. You can change this by specifying a time zone in settings.py.

To change your site's time zone

Modify the TIME_ZONE setting in settings.py

Example ~/eb-djangoproj/eb-djangoproj/settings.py

Internationalization

LANGUAGECODE = 'en-us'
TIME
ZONE = 'US/Pacific'
USEI18N = True
USE
L10N = True
USE_TZ = True

For a list of time zones, visit this page.

Deploy the application to your Elastic Beanstalk environment:

~/eb-djangoproj/$ eb deploy

Create a Site Administrator

You can create a site administrator for your Django application to access the admin console directly from the web site. Administrator login details are stored securely in the local database image included in the default project that Django generates.

To create a site administrator

Initialize your Django application's local database:

~/eb-djangoproj$ python manage.py migrate
Operations to perform:  
  Apply all migrations: admin, contenttypes, auth, sessions
Running migrations:  
  Rendering model states... DONE
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying sessions.0001_initial... OK

Run python manage.py createsuperuser to create an administrator:

~/eb-djangoproj$ python manage.py createsuperuser
Username: thiscooladmin  
Email address: me@mcraigderington.me  
Password: ****************  
Password (again): ****************  
Superuser created successfully.  
Deploy Your Django App
~/eb-djangoproj$ eb deploy

View the admin console by opening the local site in your browser, appending /admin/ to the site URL, such as:

http://djang-env.path.us-west-2.elasticbeanstalk.com/admin/

Log in with the username and password that you configured in step 2:

You can use a similar process of local updating/testing followed by eb deploy. Elastic Beanstalk takes care of the work of updating your live servers, so you can focus on application development instead of server administration!

Add a Database Migration Configuration File

You can add commands to your .ebextensions script that will be run when your site is updated. This allows you to automatically generate database migrations.

To add a migrate step when your application is deployed

Create a new configuration file named db-migrate.config with the following content:

Example ~/eb-djangoproj/.ebextensions/db-migrate.config

container_commands:  
  01_migrate:
    command: "django-admin.py migrate"
    leader_only: true
option_settings:  
  aws:elasticbeanstalk:application:environment:
    DJANGO_SETTINGS_MODULE: ebdjango.settings

This configuration file runs the django-admin.py migrate command during the deployment process, prior to starting your application. Because it runs prior to the application starting, you must also configure the DJANGO_ SETTINGS _ MODULE environment variable explicitly (usually wsgi.py takes care of this for you during startup).

** Specifying leader_only: true in the command ensures that it is run only once when you're deploying to multiple instances.

Deploy your application:

~/eb-djangoproj$ eb deploy
Clean Up and Next Steps

To save hours and other AWS resources between development sessions, terminate your Elastic Beanstalk environment with eb terminate:

~/eb-djangoproj$ eb terminate django-env

You have now successfully deployed your Django-powered app to Amazon's Elastic Beanstalk.

Congrats!

Craig Derington

Veteran full stack web dev focused on deploying high-performance, responsive, modern web applications using Python, NodeJS, Django, Flask, MongoDB and MySQL.

comments powered by Disqus