Piotr Rogulski
Piotr Rogulski
Author · Python developer
Jun 9, 2019 4 min read

Have you ever considered AWS Elastic Beanstalk for Django?

AWS elastic beanstalk django

Introduction

AWS Elastic Beanstalk is easy-to-use Amazon service for deploying and scaling web applications in couple languages including Python.

The best solution if you are short on time with setting the whole server setup and on DevOps resources. AWS EB takes care of everything for you: HTTP server, language interpreter, operating system, host, load balancer and everything what you really need if it comes to a modern web app.

This post will contain a simple guide for Django setup using AWS Elastic Beanstalk with database configuration and all stuff which you will need to kick off with a project!

Source code can be found on my github.

Setup:

  • AWS and Elastic Beanstalk configuration and RDS DB
  • Django project creation
  • Django migrations & collect static & Django admin

Instructions

  1. Install aws cli

    brew install awsebcli 

  2. Configure access to AWS account

    aws configure 

  3. Create a django project

    django-admin startproject django_eb 

  4. Initialize elastic beanstalk app. It will create .elasticbeanstal directory with config.yml

    eb init

  5. Create an elastic beanstalk environment. This will be also available to see in AWS console

    eb create <environment_name>

    Note:

    • Unfortunately looks like only US regions only are supported for Elastic Beanstalk… At least for me, only US regions worked… For other regions, I got an error message that account is blocked and to contact support.
  6. Create a .ebextensions directory with will contain all eb configs and django.config file inside

        .
        ├── .ebextensions
        │   └── django.config
        ├── .elasticbeanstalk
        │   └── config.yml
        ├── django_eb
        │   ├── __init__.py
        │   ├── settings.py
        │   ├── urls.py
        │   └── wsgi.py
        ├── manage.py
        ├── requirements.txt
        

  7. Update django.config file with:

    • Migration command: Will do a migration on deploy
    • Create admin command: To init Django admin without a login on the machine
    • Collect static command: Generate static files for Django on the machine
        container_commands:
          01_migrate:
            command: "source /opt/python/run/venv/bin/activate && python manage.py migrate --noinput"
            leader_only: true
          02_create_admin:
            command: "source /opt/python/run/venv/bin/activate && python manage.py createadmin"
          03_collectstatic:
            command: "source /opt/python/run/venv/bin/activate && python manage.py collectstatic --noinput"
            leader_only: true
    
        option_settings:
          aws:elasticbeanstalk:container:python:
              WSGIPath: django_eb/wsgi.py
          aws:elasticbeanstalk:application:environment:
            DJANGO_SETTINGS_MODULE: django_eb.settings
          aws:elasticbeanstalk:container:python:staticfiles:
            "/static/": "www/static/"
        
  8. Create a Django command to create admin from code using custom command.

        from django.core.management.base import BaseCommand
        from django.contrib.auth.models import User
    
        from django_eb import settings
    
    
        class Command(BaseCommand):
    
            def handle(self, *args, **options):
                if not User.objects.filter(username=settings.DEFAULT_ADMIN_NAME).exists():
                    User.objects.create_superuser(
                        settings.DEFAULT_ADMIN_NAME, 
                        settings.DEFAULT_ADMIN_EMAIL, 
                        settings.DEFAULT_ADMIN_PASSWORD,
                    )
    
        

    Make sure that command is placed in right directory: <app_name>/management/commands/createadmin.py file.

        .
        ├── .ebextensions
        │   └── django.config
        ├── .elasticbeanstalk
        │   └── config.yml
        ├── django_eb
        │   ├── __init__.py
        │   ├── settings.py
        │   ├── urls.py
        │   ├── wsgi.py
        │   ├── management
        │   ├── __init__.py
        │   └── commands
        │       ├── __init__.py
        │       └── createadmin.py
        ├── manage.py
        ├── requirements.txt
        
  9. Add config variables to the settings.py

        DEFAULT_ADMIN_PASSWORD = os.environ.get('DEFAULT_ADMIN_PASSWORD')
        DEFAULT_ADMIN_NAME = os.environ.get('DEFAULT_ADMIN_NAME')
        DEFAULT_ADMIN_EMAIL = os.environ.get('DEFAULT_ADMIN_EMAIL')
    
        STATIC_ROOT = 'www/static/'
        

  10. Setting up a database: Go to your AWS account -> Elastic Beanstalk -> Configuration and

    RDS AWS database for Django

  11. AWS eb automatically will add environment variables to the instance so the only thing what should be done is to update DATABASE in settings.py

        if 'RDS_DB_NAME' in os.environ:
            DATABASES = {
                'default': {
                    'ENGINE': 'django.db.backends.postgresql',
                    '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'],
                }
            }
    
        

  12. By default, Amazon instance runs on Amazon Linux (distribution evolved from RedHat and CentOS). To run postgresql we need to install yum packages otherwise error Error: pg_config executable not found will be raised.

    Add packages.config file to the .ebextensions:

        packages:
          yum:
            git: []
            postgresql93-devel: []
        
  13. Now, when the whole setup is completed we are ready to deploy our application

        eb deploy

AWS elastic beanstalk django

Troubleshooting

  • RDS database configuration in AWS panel will be only possible when Elastic Beanstalk instance will be working and the app health will be ok
  • If you are getting an error: account is currently blocked and not recognized as a valid account try to change the region to US
  • Remember to add psycopg2 in your requirements.txt to get PostgreSQL working
  • RDS database is not a scalable as the Elastic Beanstalk, consider to use Aurora service
  • Add your generated host into ALLOWED_HOSTS settings, otherwise you will get invalid host error

Summary

I’m mostly building web apps on top of Google Could Platform with special care of App Engine. I decided to give a try to AWS for my next project and I can already see great potential.

This configuration with reading documentation took me about 1h. After this 1h I’ve got working and deployed Django application and I was ready to start implementing a domain features.

Awesome thing in AWS is that you can use all their services using IAM permissions in each service. Google services aren’t so great… so if you would like to use Google Memory Store with App Engine Standard you can already stop, check this article to get more info.

If you would like to get more information about the AWS Elastic Beanstalk, please check their documentation. They are also having a great tutorial how to set up Django on EBS but with a little less information.




comments powered by Disqus