Django AWS Deployment
Introduction
Deploying a Django application to production requires a robust, scalable, and reliable hosting environment. Amazon Web Services (AWS) provides one of the most comprehensive cloud platforms available today, offering services that can handle everything from hosting your application code to managing your database and serving static files.
In this tutorial, we'll walk through the process of deploying a Django application on AWS, covering the following key AWS services:
- EC2 (Elastic Compute Cloud) - Virtual servers to run your Django application
- RDS (Relational Database Service) - Managed database service for your application data
- S3 (Simple Storage Service) - Object storage for your static and media files
- Elastic IP - Static IP address for your application
- Route 53 - Domain name service (optional)
By the end of this guide, you'll have your Django application running in a production environment that can scale with your needs.
Prerequisites
Before starting this tutorial, make sure you have:
- A functioning Django application ready for deployment
- An AWS account
- Basic familiarity with Linux commands
- Git for version control
- Basic understanding of how Django works
Setting Up Your AWS Environment
Step 1: Create an EC2 Instance
Let's start by creating a virtual server using Amazon EC2:
- Log into your AWS Management Console
- Navigate to EC2 service
- Click "Launch Instance"
- Choose an Amazon Machine Image (AMI) - Ubuntu Server 22.04 LTS is recommended for beginners
- Select an instance type (t2.micro is eligible for free tier)
- Configure instance details (defaults are fine for now)
- Add storage (defaults are usually sufficient for a starter project)
- Add tags (optional but recommended, e.g., Name: django-app)
- Configure security group:
- Allow SSH (port 22)
- Allow HTTP (port 80)
- Allow HTTPS (port 443)
- Review and launch
- Create or select an existing key pair (save the .pem file securely)
Step 2: Allocate an Elastic IP
To ensure your server has a fixed public IP address:
- In the EC2 dashboard, navigate to "Elastic IPs"
- Click "Allocate Elastic IP address"
- Click "Allocate"
- Select the newly allocated IP and click "Actions" → "Associate Elastic IP address"
- Select your EC2 instance and click "Associate"
Step 3: Connect to Your EC2 Instance
Open a terminal on your local machine and connect to your EC2 instance:
chmod 400 your-key-pair.pem
ssh -i your-key-pair.pem ubuntu@your-elastic-ip
Setting Up Your Server
Step 1: Update the System
Once logged in to your EC2 instance, update the system packages:
sudo apt update
sudo apt upgrade -y
Step 2: Install Required Packages
Install the necessary software for running Django:
sudo apt install -y python3-pip python3-dev libpq-dev postgresql postgresql-contrib nginx git
Step 3: Create a Virtual Environment
Create and activate a Python virtual environment for your project:
sudo pip3 install virtualenv
mkdir ~/myproject
cd ~/myproject
virtualenv venv
source venv/bin/activate
Setting Up a Database with RDS
Although you could install PostgreSQL directly on your EC2 instance, using Amazon RDS provides better scalability, automated backups, and maintenance.
Step 1: Create an RDS Instance
- Navigate to the RDS service in the AWS Management Console
- Click "Create database"
- Select "PostgreSQL"
- Choose "Free tier" if eligible
- Set the DB instance identifier (e.g., django-db)
- Set master username and password (save these securely)
- Under "Connectivity", select your EC2 instance's security group
- Create the database
Step 2: Configure Security Group
You need to allow your EC2 instance to connect to your RDS:
- Go to the RDS dashboard and click on your database
- Note the "Endpoint" (you'll need this later)
- Click on the security group used by your RDS
- Add an inbound rule allowing PostgreSQL (port 5432) from your EC2 security group
Deploying Your Django Project
Step 1: Clone Your Project
On your EC2 instance, clone your Django project repository:
git clone https://github.com/yourusername/your-django-project.git
cd your-django-project
Step 2: Install Requirements
Install your project dependencies:
pip install -r requirements.txt
If you don't have a requirements file, you should at least install:
pip install django gunicorn psycopg2-binary
Step 3: Configure Django Settings
Create a production settings file or modify your existing settings to use environment variables for sensitive information:
# settings.py
import os
DEBUG = False
ALLOWED_HOSTS = ['your-elastic-ip', 'your-domain.com']
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'your_db_name',
'USER': 'your_db_username',
'PASSWORD': 'your_db_password',
'HOST': 'your-rds-endpoint.rds.amazonaws.com',
'PORT': '5432',
}
}
# Static files configuration for S3
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
Step 4: Set Up Static Files with S3 (Optional but Recommended)
Amazon S3 is great for serving static and media files. Let's configure it:
- Create an S3 bucket in the AWS Management Console
- Install django-storages and boto3:
pip install django-storages boto3
- Add to your settings.py:
# settings.py
INSTALLED_APPS += ['storages']
AWS_ACCESS_KEY_ID = 'your-access-key'
AWS_SECRET_ACCESS_KEY = 'your-secret-key'
AWS_STORAGE_BUCKET_NAME = 'your-bucket-name'
AWS_S3_CUSTOM_DOMAIN = f'{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com'
AWS_DEFAULT_ACL = 'public-read'
# Static files
STATICFILES_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
STATIC_URL = f'https://{AWS_S3_CUSTOM_DOMAIN}/'
# Media files
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
MEDIA_URL = f'https://{AWS_S3_CUSTOM_DOMAIN}/media/'
Step 5: Deploy Django
Initialize your Django project on the server:
python manage.py migrate
python manage.py collectstatic
python manage.py createsuperuser
Setting Up Gunicorn
Gunicorn is a Python WSGI HTTP server that will run your Django application.
Step 1: Create a Gunicorn Service File
Create a systemd service file for Gunicorn:
sudo nano /etc/systemd/system/gunicorn.service
Add the following:
[Unit]
Description=gunicorn daemon
After=network.target
[Service]
User=ubuntu
Group=www-data
WorkingDirectory=/home/ubuntu/your-django-project
ExecStart=/home/ubuntu/myproject/venv/bin/gunicorn \
--access-logfile - \
--workers 3 \
--bind unix:/home/ubuntu/your-django-project/myproject.sock \
your_project_name.wsgi:application
[Install]
WantedBy=multi-user.target
Start and enable the Gunicorn service:
sudo systemctl start gunicorn
sudo systemctl enable gunicorn
Setting Up Nginx
Nginx will act as a reverse proxy to Gunicorn.
Step 1: Create an Nginx Configuration
sudo nano /etc/nginx/sites-available/myproject
Add the following configuration:
server {
listen 80;
server_name your-elastic-ip your-domain.com;
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
alias /home/ubuntu/your-django-project/staticfiles/;
}
location / {
include proxy_params;
proxy_pass http://unix:/home/ubuntu/your-django-project/myproject.sock;
}
}
Create a symbolic link to enable the site:
sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled
Test the Nginx configuration and restart:
sudo nginx -t
sudo systemctl restart nginx
Step 2: Configure Firewall (Optional)
If you have UFW enabled, allow Nginx and SSH:
sudo ufw allow 'Nginx Full'
sudo ufw allow 'OpenSSH'
sudo ufw enable
Setting Up HTTPS with Let's Encrypt (Optional)
If you have a domain name pointed to your server, you can secure it with Let's Encrypt:
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d your-domain.com
Follow the prompts to complete the HTTPS configuration.
Automating Deployments with GitHub Actions (Advanced)
For automatic deployments when you push to your Git repository, you can set up GitHub Actions:
- Create an SSH key on your EC2 instance:
ssh-keygen -t rsa -b 4096 -C "[email protected]"
- Add the public key to ~/.ssh/authorized_keys
- Add the private key as a GitHub secret in your repository
- Create a GitHub workflow file:
name: Deploy to AWS
on:
push:
branches: [ main ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Deploy to EC2
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
cd ~/your-django-project
git pull
source ~/myproject/venv/bin/activate
pip install -r requirements.txt
python manage.py migrate
python manage.py collectstatic --noinput
sudo systemctl restart gunicorn
Summary
In this guide, we've covered:
- Creating an EC2 instance for hosting your Django application
- Setting up a PostgreSQL database with Amazon RDS
- Deploying your Django application code
- Configuring static files with Amazon S3
- Setting up Gunicorn as an application server
- Configuring Nginx as a reverse proxy
- Securing your site with HTTPS (optional)
- Setting up automatic deployments (advanced)
AWS provides a robust platform for Django applications of any size. This setup can handle everything from small personal projects to large-scale applications with thousands of users. As your traffic grows, you can easily scale by:
- Increasing the size of your EC2 instance
- Setting up auto-scaling groups
- Implementing load balancing
- Adding caching layers like Redis or ElastiCache
Additional Resources
- AWS Documentation for EC2
- Django Deployment Checklist
- Gunicorn Documentation
- Nginx Documentation
- Let's Encrypt Documentation
Exercises
- Set up a staging environment using a separate EC2 instance with the same configuration.
- Configure CloudFront CDN to serve your static files from S3 for improved performance.
- Set up regular database backups using AWS RDS automated backup feature.
- Implement monitoring for your EC2 instance using AWS CloudWatch.
- Set up a CI/CD pipeline using GitHub Actions or AWS CodePipeline to automatically test and deploy your code.
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)