AWS Elastic Beanstalk is a PaaS (Platform As A Service) offered by Amazon Web Services for deploying and managing web applications.
It allows you to deploy your applications quickly to the cloud while letting you retain full control over your AWS application resources.
A great benefit of deploying your applications using AWS Elastic Beanstalk is that it leverages on core AWS services such as EC2, ECS, RDS, Auto Scaling and Elastic Load Balancing to streamline your setup.
$ git clone https://github.com/Papagoat/Create-a-Simple-Django-Boilerplate.git
$ cd Create-a-Simple-Django-Boilerplate/demo
$ python3 -m venv myvenv
$ source ./myvenv/bin/activate
$ pip install django
$ pip install psycopg2
$ pip install awsebcli
$ pip freeze > requirements.txt
To configure the application and environment, we need to set up an IAM user.
The new user needs to have the appropriate permissions to access the AWS Elastic Beanstalk application.
The simplest way is to search for the "AWSElasticBeanstalkFullAccess" policy in the IAM Policies console and attach it to the user or group.
See this guide on how to use Elastic Beanstalk with AWS IAM.
Avoid using the root user credentials to perform everyday AWS tasks. Create individual users with different permission settings in the IAM console instead.
See this guide on how to create your first IAM admin user and group.
We are ready to roll! First, we need to create and configure our AWS Elastic Beanstalk application. Cd into the project folder and run this command.
$ eb init
Select a default region
For best performance, choose a region closest to your intended audience.
Application Name
Leave it as default.
Select a Python version
For this tutorial, we will use the default Python EC2 image. (Option 1)
SSH
Type "y" to set up SSH. We will be using SSH to create our admin user and perform database migrations later.
RSA Keypair name
Leave it as default.
After we have configured the application, we see a hidden .elasticbeanstalk folder inside the demo folder.
Open .elasticbeanstalk/config.yml to view the different parameters.
branch-defaults:
default:
environment: null
group_suffix: null
global:
application_name: demo
branch: null
default_ec2_keyname: aws-eb2
default_platform: Python 3.6
default_region: ap-southeast-1
include_git_submodules: true
instance_profile: null
platform_name: null
platform_version: null
profile: eb-cli
repository: null
sc: null
workspace_type: Application
Run this command to create an environment for our application.
$ eb create testENV --database.engine postgres
Why not just $ eb create testENV?
If we run $ eb create testENV without creating the postgres RDS database now, we may encounter a failure later on.
This appears to be a bug with AWS.
Note down the RDS DB username and password. We need it shortly. Once completed, AWS Elastic Beanstalk will create the environment automatically.
It's a good time to grab a beer as this may take a while.
Run the following command to access the dashboard once the process is completed.
$ eb console
You may encounter an error that says "Your WSGIPath refers to a file that does not exist."
To fix that, let us change the WSGIPath in AWS Elastic Beanstalk's global configuration.
$ eb config
Scroll to the bottom where it says WSGIPath: application.py and change it to WSGIPath: demo/wsgi.py.
Hit CTRL + X to save your changes and wait for the environment to update.
We need to add our application URL to the ALLOWED_HOSTS setting. You can locate the URL from the top right corner of the application dashboard.
Add the URL to ALLOWED_HOSTS in demo/settings.py
...
ALLOWED_HOSTS = [
'your-application-url'
]
...
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'postgres',
'USER': 'your-db-username',
'PASSWORD': 'your-db-password',
'HOST': 'your-db-endpoint',
'PORT': '5432',
}
}
When we create an AWS Elastic Beanstalk environment, AWS sets the database name as postgres by default. See this guide on how to rename a DB instance.
## Static files (CSS, JavaScript, Images)
## https://docs.djangoproject.com/en/2.1/howto/static-files/
STATIC_ROOT = os.path.join(BASE_DIR,'static')
STATIC_URL = '/static/'
$ python manage.py collectstatic
$ eb deploy
AWS Elastic Beanstalk will look for the requirements.txt file and install the dependencies automatically whenever we deploy our code. Very cool!
We have to create our model tables for the application to work. We do that by connecting to our instance via SSH.
Run this command in our terminal.
$ eb ssh
Ignore the warnings and continue. We can now access the files on the AWS Elastic Beanstalk instance.
We are going to
$ source ../../opt/python/run/venv/bin/activate
$ cd ../../opt/python/current/app
$ python manage.py migrate
$ python manage.py createsuperuser
If you encounter permission errors, try adding sudo to the command. E.g. $ sudo python manage.py migrate.
In an actual live production environment, you should configure IAM permissions instead.
Exit from SSH and launch the application in the browser.
$ exit
$ eb open
$ eb open
Although this tutorial is a contrived example, it shows the ease of deploying Python applications or any web applications for that matter using AWS Elastic Beanstalk.
In a real-world situation though, we would secure the database using environment variables and leverage on AWS CodeCommit as our code repository. We would also write AWS Elastic Beanstalk configuration files and Django custom management commands to streamline the deployment further!
It may seem confusing if this is your initial foray into AWS. As you begin to understand how all the different parts fit together, you will find that deploying and managing your applications in AWS Cloud is actually pretty straightforward.