Django - Deploying on AWS

14th February, 2019

AWS Deployment using Elastic Beanstalk

Basic set up

  • Create an AWS account
  • Go to Elastic Beanstalk 
  • Download and install awsebcli
    pip install awsebcli

Django Set Up

  • Create a Django app
  • Create requirements.txt file in the project folder 
  • Install following libraries
    pip install dj-database-url # for accessing database
    pip install gunicorn # for running Python HTTP server 
  • Add dj-database-url==XX & gunicorn==XX to requirements.txt file.
  • Add the following environment variables:
    • RDS_DB_NAME
    • RDS_USERNAME
    • RDS_PASSWORD
    • RDS_HOSTNAME
    • RDS_POST
    • REDIS_URL
  • Go to settings.py file and add the following: 
    • For Database settings:

      config = {
      key: value for key, value in os.environ.items()
      }
      aws_database_url = config.get('RDS_DB_NAME', None)if aws_database_url:
      # aws production settings
      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'],
      }
      }
      else:
      # development/test settings
      DATABASES = {
      'default': {
      'ENGINE': 'django.db.backends.postgresql',
      'NAME': 'shubhamdipt',
      }
      }
    • For Cache setting:
      open_redis_url = config.get('REDIS_URL')
      if open_redis_url: CACHES = {
      'default': {
      'BACKEND': 'django.core.cache.backends.dummy.DummyCache',
      }
      }
      else:
      open_redis_url = config.get('REDIS_URL')
      CACHES = {
      "default": {
      "BACKEND": "django_redis.cache.RedisCache",
      "LOCATION": open_redis_url,
      "OPTIONS": {
      "CLIENT_CLASS": "django_redis.client.DefaultClient",
      "IGNORE_EXCEPTIONS": True,
      },
      'KEY_PREFIX': DEP_NAME,
      'VERSION': VERSION,
      'TIMEOUT': 86400, # 1 day
      },
      }
  • Create gunicorn_cofig.py in project folder and add
    import os
    import multiprocessing

    size = int(os.getenv("SIZE", 1))
    # Maximum 5 worker per 128MB
    workers = min(multiprocessing.cpu_count() * 2 + 1, size * 1)
    timeout = int(os.getenv("GUNICORN_TIMEOUT", 120))
  • Run in terminal: eb init
  • Create .ebextensions folder in project folder and add
    • 01_packages.config
      packages:
      yum:
      git: []
      postgresql95-devel: []
      libjpeg-turbo-devel: []
    • 02_python.config
      option_settings:
      "aws:elasticbeanstalk:application:environment":
      DJANGO_SETTINGS_MODULE: "<project>.settings"
      "PYTHONPATH": "/opt/python/current/app:$PYTHONPATH"
      "aws:elasticbeanstalk:container:python":
      WSGIPath: <project>/wsgi.py
      NumProcesses: 3
      NumThreads: 20
      "aws:elasticbeanstalk:container:python:staticfiles":
      "/static/": "staticfiles/"
      container_commands:
      01_migrate:
      command: "source /opt/python/run/venv/bin/activate && python manage.py migrate --noinput"
      leader_only: true
      02_collectstatic:
      command: "source /opt/python/run/venv/bin/activate && python manage.py collectstatic --noinput"
  • Commit your changes in git
  • Deploy using terminal: eb create
    Tips:
    • eb deploy <aws_app_name>  # Deploys in the aws app
    • sudo eb ssh <aws_app_name> # SSH to the aws (note: ssh key should be in the .ssh folder)
      • cd /opt/python/current/app (go tp app's directory)
      • source ../env activate (activate the virtual environment)
      • python manage.py createsuperuser (create Django superuser in aws)

Enjoy !