Thanks to:
- https://www.agiliq.com/blog/2019/01/complete-serverless-django/
- https://romandc.com/zappa-django-guide/
Deploying DJango project on AWS serverless architecture.
- Configure AWS credential
~/.aws/credentials
[default]
aws_access_key_id = "your aws_iam_access_key"
aws_secret_access_key = "your aws_iam_user_secret_key"
- Create VIRTUAL ENV
$ virtualenv -p python3 env
If windows run ...
$ env\Scripts\activate
If ubuntu or mac run ...
$ source env/bin/activate
$ sudo pip3 install -r requirements.txt
Make sure following libraries are included in requirements.txt
- Django==2.0.0
- Pillow
- mysqlclient
- boto3
- boto
- django-storages==1.6.6
- zappa
We will be using DJango v2.0.0 because of the compatibility of MySQL.
- ZAPPA
$ cd mysite/
$ zappa init
Follow on screen instructions.
Once done, open zappa_settings.json
and make sure following format is followed.
{
"dev": {
"django_settings": "mysite.settings",
"profile_name": "default",
"project_name": "mysite",
"runtime": "python3.7",
"s3_bucket": "mysite-django",
"aws_region": "us-east-1"
}
}
$ zappa deploy dev
Once done a link will be returned which we will add into mysite/settings.py
.
ALLOWED_HOSTS = ['url_returned']
We push updates to AWS.
$ zappa update dev
- S3 Bucket
Add following lines into your S3 bucket CORS policy.
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>HEAD</AllowedMethod>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>PUT</AllowedMethod>
<AllowedMethod>POST</AllowedMethod>
<AllowedMethod>DELETE</AllowedMethod>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>
Add following lines into mysite/settings.py
.
Make sure to change
INSTALLED_APPS = [
...,
'storages',
....
]
AWS_STORAGE_BUCKET_NAME = "mysite-django"
AWS_S3_CUSTOM_DOMAIN = '%s.s3.amazonaws.com' % AWS_STORAGE_BUCKET_NAME
AWS_ACCESS_KEY_ID = "iam_user_access_key"
AWS_SECRET_ACCESS_KEY = "iam_user_secret_key"
AWS_S3_FILE_OVERWRITE = False
AWS_S3_OBJECT_PARAMETERS = {
'CacheControl': 'max-age=86400',
}
AWS_LOCATION = 'static'
MEDIAFILES_LOCATION = 'media'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'mysite/static'),
]
STATIC_URL = 'https://%s/%s/' % (AWS_S3_CUSTOM_DOMAIN, AWS_LOCATION)
STATICFILES_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
DEFAULT_FILE_STORAGE = 'mysite.storage_backends.MediaStorage'
AWS_SECURITY_TOKEN_IGNORE_ENVIRONMENT = True
STATIC_URL = '/static/'
MEDIA_URL = '/media/'
Create a new file mysite/storage_backends.py
.
from storages.backends.s3boto3 import S3Boto3Storage
class MediaStorage(S3Boto3Storage):
location = 'media'
file_overwrite = False
Upload static files to S3 Bucket
$ python3 manage.py collectstatic
Make sure static folder exists in mysite/ folder.
Once done update, AWS.
$ zappa update dev
NOTE: Setting Up Routing to allow file upload on AWS
- Go to VPC service and create endpoint.
- Make sure to link with existing subnets.
.
- Database MySQL.
We will setup RDS, Aurora MySQL database. Go to RDS service and create Database.
- Standard Create
- Amazon Aurora
- Amazon Aurora with MySQL compatibility
- Aurora (MySQL)-5.6.10a
- Regional
- Serverless
- Database name and username must be lowercase
- Create Password
- Select Capacity
Click on Create.
- Go to Lamda Service
- Select Lamda function
- Scroll Down to network and add subnets and security group
- Click save
- Go to security group located on the bottom right side of the database page you just created.
- At the bottom add inboud rule with Aurora/MYSQL, TCP, port 3306, and CUSTOM Security Group.
Add following lines of code in settings.py
.
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'mysitedb', # dbname
'USER': 'mysiteadmin', # master username
'PASSWORD': 'password', # master password
'PORT': '3306',
'HOST': 'mysitedb.cluster-cmrgi4dsutgn.us-east-1.rds.amazonaws.com', # Endpoint
}
}
Create a folder in mysite + all other apps with name management
.
Filestructure should be as follows.
.
├── commands
│ ├── create_db.py
│ └── __init__.py
└── __init__.py
Add following code in create_db.py
.
# mysite/management/commands/create_db.py
import sys
import logging
import MySQLdb
from django.core.management.base import BaseCommand, CommandError
from django.conf import settings
rds_host = 'mysitedb.cluster-cmrgi4dsutgn.us-east-1.rds.amazonaws.com'
db_name = 'mysitedb'
user_name = 'mysiteadmin'
password = 'password'
port = 3306
logger = logging.getLogger()
logger.setLevel(logging.INFO)
class Command(BaseCommand):
help = 'Creates the initial database'
def handle(self, *args, **options):
print('Starting db creation')
try:
db = MySQLdb.connect(host=rds_host, user=user_name,
password=password, db="mysql", connect_timeout=5)
c = db.cursor()
print("connected to db server")
c.execute("""CREATE DATABASE mysitedb;""")
c.execute(
"""GRANT ALL PRIVILEGES ON db_name.* TO 'mysite_admin' IDENTIFIED BY 'mysiteadmin';""")
c.close()
print("closed db connection")
except:
logger.error(
"ERROR: Unexpected error: Could not connect to MySql instance.")
sys.exit()
Make sure to change according to your requirement. Change CREATE DATABASE "mysitedb" => database name
Once done update code on AWS.
$ zappa update dev
We create tables.
$ zappa manage dev create_db
If you face any mysql database problems add following lines into mysite/__init__.py
.
import pymysql
pymysql.install_as_MySQLdb()
And install pymysql
library.
$ pip3 install pymysql
Run migrations.
$ zappa manage dev migrate
Create Super User
$ zappa invoke --raw dev "from django.contrib.auth.models import User; User.objects.create_superuser('admin', 'admin@admin.com', 'admin')"