Deploying a Django app on AWS
Overview
All of these steps are performed locally.
Prerequisites
I didn't realize this at first, but these prerequisites are all local. The first time I tried this out, I thought I had to get on a remote server to install Python, Django, awsebcli, etc. All of these things are installed on the local workstation and eb deploy handles moving them over and replicating the app environment.
AWS Elastic Beanstalk
Existing Elastic Beanstalk applications and environments can be found in the AWS Elastic Beanstalk management console.
Create a ne Elastic Beanstalk application from the command line one a local workstation,
$ eb init
This will prompt for region, credentials, application name, python version, ssh availability, etc.
These properties are stored in .elasticbeanstalk/config.yml which should not be added to Git.
Create a new Elastic Beanstalk environment from the command line on a local workstation. Assuming that the instance is using an independent RDS.
$ eb create
If instead the Elastic Beanstalk environment is creating its own database, it's necessary to specify that option with the create command:
$ eb create --database.engine postgres
This will prompt for the environment name, its URL prefix, and a database username and password.
Grant RDS access for the Elastic Beanstalk environment
If the environment needs access to an independent RDS instance, it's necessary to add some configuration properties or else eb deploy will generate errors to the effect that the local development db host was not found.
- AWS EB console
- EB app > EB environment > Configuration > Instances
- Instance profile: Add
rds-launch-wizard,(The comma separates the new profile from existing profiles.)
- Instance profile: Add
- EB app > EB environment > Configuration > Software Configuration > Environment Properties
RDS_DB_NAMERDS_HOSTNAMERDS_PASSWORDRDS_PORTRDS_USERNAME
Deploying a Django app
Updates to the app are deployed with eb deploy.
This looks at .elasticbeanstalk/config.yml for the target application and environment.
branch-defaults:
master:
environment: nrose-env
global:
application_name: north-rose
default_ec2_keyname: nrosedevs-aws
default_platform: 64bit Amazon Linux 2015.09 v2.0.6 running Python 3.4
default_region: us-west-2
profile: eb-cli
sc: git
With the master Git branch checked out, and the config.yml above, eb deploy will package up the project file and upload them to the EC2 instance corresponding with the nrose-env environment of the north-rose app.
To update a staging environment, edit config.yml with the following:
branch-defaults:
master:
environment: nrose-env
staging:
environment: nrose-staging
staging-nodebug:
environment: nrose-staging
With the staging Git branch checked out, eb deploy will now update the nrose-staging environment.
Alternatively, use eb deploy alternate-env to target a non-default EB environment named alternate-env.
Installing Django app dependencies
See Defining Django App Dependencies
Production environment project settings
Set DEBUG to False:
# myapp/settings.py # ... DEBUG = False
With DEBUG = False, ALLOWED_HOSTS is required. [1]
Add localhost, the domain of the site, Elastic Beanstalk, and AWS's Elastic Load Balancer to ALLOWED_HOSTS:
# myapp/settings.py
# ...
DEBUG = False
ALLOWED_HOSTS = [
"localhost",
"mydomain.com",
".us-west-2.elasticbeanstalk.com",
".compute-1.amazonaws.com" # allow viewing of instances directly
]
# Grant access to AWS's Elastic Load Balancer
import requests
EC2_PRIVATE_IP = None
try:
EC2_PRIVATE_IP = requests.get('http://169.254.169.254/latest/meta-data/local-ipv4', timeout=0.01).text
except requests.exceptions.RequestException:
pass
if EC2_PRIVATE_IP:
ALLOWED_HOSTS.append(EC2_PRIVATE_IP)
It's necessary to install python-requests for the above code. (pip install requests).
Configuring an independent RDS instance
See Using Elastic Beanstalk With Amazon RDS
- Run
makemigrationlocally. This prevents potential data loss on the production server.eb deploywill move the migrations file to the EC2 instance and have them ready to run amigrate. - Deploy the project using
eb createoreb deploy. - Set up a
.configcommand to run the migration.
Serving static files using Amazon S3
Configuration
See Configuring Django to Serve Media Files Via S3 and []
Deployment
Once configured to use S3 for storage, Django's collectstatic command will upload static files to the S3 bucket. Both the AWS servers and local development will reference the files on S3.
This means that if a stylesheet is compiled, the collectstatic command must be run before the changes are available anywhere.
$ python manage.py collectstatic --noinput
The static template tag will correctly reference static resources in the Amazon S3 bucket.
Notes
See also
- Deploying a Django Application - AWS Elastic Beanstalk documentation
- Deploying a Django app to AWS Elastic Beanstalk - Real Python (Jan. 22, 2015)
- Django and Amazon AWS Elastic Beanstalk with S3 - Racing Tadpole, June 15, 2013
Some information about using S3 for a file system.) - How to Make Django's ALLOWED_HOSTS work with AWS ELB Health Checks - Dryan, Jan 5, 2014
References
- ↑ ALLOWED_HOSTS - Django documentation