In this guide, we will walk you through the entire process of deploying a Django application to AWS using Jenkins and GitHub Actions. By following these steps, you will be able to automate CI/CD pipelines, manage infrastructure using Jenkins and GitHub Actions, and ensure a scalable and reliable deployment for your Django applications.
Introduction
Deploying web applications has evolved significantly with the introduction of cloud platforms and DevOps tools. Combining Django, Jenkins, and GitHub Actions allows developers to leverage the benefits of Continuous Integration and Continuous Deployment (CI/CD), automated testing, and consistent delivery pipelines.
AWS (Amazon Web Services) offers a scalable and secure environment to deploy and host Django applications. With services like EC2 for compute power, S3 for storage, and RDS for databases, AWS simplifies infrastructure management for large-scale applications.
What You Will Learn:
- Setting up an AWS EC2 instance for hosting Django applications.
- Installing Jenkins on AWS EC2 for automated CI/CD.
- Using Jenkins and GitHub Actions to automate the deployment process.
- Configuring AWS services like S3 and RDS to support Django applications.
Prerequisites and Initial Setup
Before starting, ensure you have the following prerequisites:
- AWS Account: You need an active AWS account to create resources such as EC2, S3, and RDS.
- Django Application: Prepare a Django project with a
requirements.txt
file and aDockerfile
if you are using Docker. - EC2 Key Pair: Create an EC2 key pair to enable SSH access to your EC2 instances.
- IAM User: Set up an IAM user with permissions to manage AWS resources like EC2, S3, and RDS.
Initial Setup:
- Create an S3 Bucket: Go to the AWS S3 console and create a new bucket for storing static and media files. Configure bucket permissions to allow access only to specific IAM roles.
- Create an RDS Instance: Set up a new PostgreSQL RDS database. Note down the endpoint, username, and password for configuring your Django application.
- Set Up a Virtual Environment: Create a Python virtual environment for your Django project and install dependencies using
pip
.
# Create a virtual environment
python3 -m venv venv
# Activate the virtual environment
source venv/bin/activate
# Install dependencies
pip install -r requirements.txt
Setting Up AWS EC2 for Django Deployment
Create an EC2 Instance:
- Go to the EC2 dashboard and click "Launch Instance."
- Choose the Amazon Linux 2 AMI (or Ubuntu 22.04 LTS if you prefer).
- Select the instance type, such as `t2.micro` for small-scale applications.
- Configure instance details, such as VPC, subnet, and IAM role if needed.
- Add storage and configure a security group to allow HTTP (port 80), HTTPS (port 443), and SSH (port 22) traffic.
Connect to the EC2 Instance:
After launching the instance, connect using SSH from your local machine:
ssh -i "your-key.pem" ec2-user@ec2-xx-xxx-xxx-xx.compute.amazonaws.com
Replace your-key.pem
with the path to your key pair file, and ec2-xx-xxx-xxx-xx.compute.amazonaws.com
with your EC2 public IP or DNS.
Install Required Software:
- Update the package list and install Python, pip, Git, and Docker.
sudo yum update -y
sudo yum install -y python3 python3-pip git docker
- Start Docker and add the EC2 user to the Docker group to avoid permission issues:
sudo service docker start
sudo usermod -aG docker ec2-user
- Install other necessary tools like
nginx
if you plan to use it as a reverse proxy.
Installing and Configuring Jenkins on AWS EC2
Jenkins is a popular automation server used for building, testing, and deploying code. We'll install Jenkins on the EC2 instance and set up a basic pipeline for deploying Django applications.
Install Jenkins:
- Add the Jenkins repository and import the GPG key:
sudo wget -O /etc/yum.repos.d/jenkins.repo \
https://pkg.jenkins.io/redhat-stable/jenkins.repo
sudo rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io.key
- Install Jenkins and Java:
sudo yum install jenkins java-11-openjdk-devel -y
- Start the Jenkins service and enable it to run on boot:
sudo systemctl start jenkins
sudo systemctl enable jenkins
Configure Jenkins:
- Open Jenkins in a browser using
http://<EC2_Public_IP>:8080
. - Retrieve the initial admin password:
sudo cat /var/lib/jenkins/secrets/initialAdminPassword
- Complete the Jenkins setup wizard and install recommended plugins.
Install Jenkins Plugins:
- Install the following plugins for Django projects: Git, GitHub, Docker, SSH Agent, and Ansible.
- Create a new Jenkins pipeline and integrate it with your GitHub repository.
Creating a Jenkins Pipeline for Django Deployment
- Create a
Jenkinsfile
:
The Jenkinsfile
defines the steps Jenkins will take to build, test, and deploy your application. Place the file in the root of your Django project.
pipeline {
agent any
environment {
AWS_ACCESS_KEY_ID = credentials('AWS_ACCESS_KEY')
AWS_SECRET_ACCESS_KEY = credentials('AWS_SECRET_KEY')
}
stages {
stage('Build') {
steps {
echo 'Building the project...'
sh 'pip install -r requirements.txt'
}
}
stage('Test') {
steps {
echo 'Running tests...'
sh 'python manage.py test'
}
}
stage('Deploy') {
steps {
echo 'Deploying the application...'
sshagent (credentials: ['ec2-ssh-key']) {
sh '''
ssh -o StrictHostKeyChecking=no ec2-user@ec2-xx-xxx-xxx-xx.compute.amazonaws.com << EOF
cd /var/www/myapp
git pull origin main
source venv/bin/activate
pip install -r requirements.txt
python manage.py migrate
sudo systemctl restart gunicorn
EOF
'''
}
}
}
}
}
In this Jenkinsfile
, replace the placeholders like AWS_ACCESS_KEY
and ec2-ssh-key
with your actual Jenkins credentials. This pipeline will install dependencies, run tests, and deploy the code to your EC2 instance using SSH.
Setting Up GitHub Actions for CI/CD
GitHub Actions is a powerful CI/CD tool that integrates seamlessly with GitHub repositories. It allows you to automate workflows for testing, building, and deploying applications.
- Create a GitHub Actions Workflow:
Create a .github/workflows/deploy.yml
file in your GitHub repository:
name: Django CI/CD
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: 3.8
- name: Install dependencies
run: pip install -r requirements.txt
- name: Run Tests
run: python manage.py test
- name: Deploy to EC2
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
EC2_INSTANCE: 'ec2-user@ec2-xx-xxx-xxx-xx.compute.amazonaws.com'
SSH_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
run: |
echo "$SSH_KEY" > deploy_key.pem
chmod 400 deploy_key.pem
scp -i deploy_key.pem -o StrictHostKeyChecking=no -r * $EC2_INSTANCE:/var/www/myapp/
ssh -i deploy_key.pem $EC2_INSTANCE 'cd /var/www/myapp && source venv/bin/activate && pip install -r requirements.txt && python manage.py migrate && sudo systemctl restart myapp'
Configuring AWS S3 and RDS for Django Storage and Database
Configure S3 for Static and Media Files:
- Install
boto3
anddjango-storages
:
pip install boto3 django-storages
- Update
settings.py
:
AWS_ACCESS_KEY_ID = os.getenv('AWS_ACCESS_KEY_ID')
AWS_SECRET_ACCESS_KEY = os.getenv('AWS_SECRET_ACCESS_KEY')
AWS_STORAGE_BUCKET_NAME = 'my-django-bucket'
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
- Configure RDS: Update the
DATABASES
configuration insettings.py
to point to your RDS PostgreSQL instance:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'mydatabase',
'USER': 'myuser',
'PASSWORD': 'mypassword',
'HOST': 'mydbinstance.cxyzzzzzz.us-east-1.rds.amazonaws.com',
'PORT': '5432',
}
}
Deploying Django Application to AWS Using Jenkins
- Set Up Gunicorn and Nginx:
- Install Gunicorn and Nginx on your EC2 instance:
sudo yum install nginx
sudo pip install gunicorn
Create a Gunicorn Service:
Create a Gunicorn service file at
/etc/systemd/system/gunicorn.service
:
[Unit]
Description=gunicorn daemon for Django project
After=network.target
[Service]
User=ec2-user
Group=nginx
WorkingDirectory=/var/www/myapp
ExecStart=/var/www/myapp/venv/bin/gunicorn --workers 3 --bind unix:/var/www/myapp/myapp.sock myapp.wsgi:application
[Install]
WantedBy=multi-user.target
Configure Nginx:
Set up Nginx as a reverse proxy:
server {
listen 80;
server_name mydomain.com;
location / {
proxy_pass http://unix:/var/www/myapp/myapp.sock;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /static/ {
alias /var/www/myapp/static/;
}
location /media/ {
alias /var/www/myapp/media/;
}
}
- Restart Services:
- Restart Gunicorn and Nginx:
sudo systemctl start gunicorn
sudo systemctl enable gunicorn
sudo systemctl restart nginx
Deploying Django Application Using GitHub Actions
GitHub Actions can also be used to deploy your Django application to AWS. Set up secrets in your GitHub repository, such as AWS_ACCESS_KEY_ID
, AWS_SECRET_ACCESS_KEY
, and SSH_PRIVATE_KEY
.
The GitHub Actions workflow will build the Docker image, push it to an AWS ECR (Elastic Container Registry), and deploy it to an ECS (Elastic Container Service) cluster or directly to EC2.
- Build and Push Docker Image to ECR:
- Add a
Dockerfile
in your Django project root and define the environment. - Use GitHub Actions to build and push the image:
- name: Build Docker Image
run: docker build -t my-django-app .
- name: Login to AWS ECR
run: $(aws ecr get-login --no-include-email --region us-east-1)
- name: Push Docker Image to ECR
run: docker push <AWS_ACCOUNT_ID>.dkr.ecr.us-east-1.amazonaws.com/my-django-app:latest
- Deploy Docker Container to ECS:
- Create a task definition in ECS and deploy the Docker container.
Configuring Domain and SSL for Django Application
- Set Up Route 53:
Create a hosted zone and add a record set pointing to your EC2 instance.
Use AWS Certificate Manager:
- Request an SSL certificate and configure Nginx to use the certificate.
server {
listen 443 ssl;
server_name mydomain.com;
ssl_certificate /etc/letsencrypt/live/mydomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mydomain.com/privkey.pem;
location / {
proxy_pass http://unix:/var/www/myapp/myapp.sock;
}
}
Monitoring and Logging Django Applications on AWS
- Use CloudWatch for logs and set up alarms.
- Install
watchtower
to ship logs to CloudWatch from your Django application.
Troubleshooting Common Issues
- SSH Connection Issues: Check security group rules and SSH key permissions.
- Jenkins Pipeline Failures: Review logs for syntax errors and permission issues.
- GitHub Actions Workflow Failures: Check
deploy_key.pem
permissions andssh
command syntax.
Security Best Practices
- Use IAM roles instead of hardcoding credentials.
- Enable multi-factor authentication (MFA) for IAM users.
- Restrict access to sensitive resources using security groups.
Cost Optimization
- Use
t2.micro
instances for testing andt3.medium
for production. - Utilize S3 lifecycle policies to transition infrequently accessed objects.
Future Enhancements
- Implement load balancing with an AWS ALB.
- Set up auto-scaling groups for EC2 instances.
- Explore AWS Lambda for serverless functions and microservices.