AWS CI-CD for your Django app with AWS CodePipeline
Tags: django, aws, devops, github
Published: 2022-10-01 05:25:08

# What is CI/CD pipeline?
As a developer we would like to keep our entire focus on production instead of manually testing and deploying each time, that's where automating the process with CI/CD reduces the effort of deployment process, CI/CD refers to creating a code pipeline where code changes are committed, tested and then deployed without any manual interference. Basically, a developer can add a new feature to their codebase and push updates in an efficient, streamlined process.

# What are some common CI/CD tools?

- Travis CI/CD
- Jenkins
- Buddy
- CircleCI
- Gitlab
- Codeship
- **AWS Codepipeline**

This guide covers all steps needed for setting up your CI-CD workflow with AWS CodePipeline and GitHub under the hood. In this tutorial we will clone a sample django application from GitHub, configure CodeDeploy agent in EC2 and finally setup our CI-CD pipeline in AWS.

![Django-AWS CI-CD](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h1vzt4wk2um4m0c8mn1n.jpg)
_Link to sample django project:_ [GitHub](https://github.com/vinclairvoyant/django-aws_cicd)

**Table of Contents**

1. [Clone GitHub repo](#1)
2. [Preparing Django project files](#2)
3. [Create yaml files to automate AWS CI-CD](#3)
4. [Create roles in AWS](#8)
5. [Launching EC2 instance for AWS CI-CD](#5)
6. [Configure AWS Code Deploy](#6)
7. [Configure AWS Code Pipeline](#7)

<h3>
<a name="1" href="#1" class="anchor"></a>
1. Clone GitHub repo
</h3>

Open your chosen command-line interface and clone the repository with the below command:

```
$ git clone git@github.com:vinclairvoyant/django-aws_cicd.git
```


<h3>
<a name="2" href="#2" class="anchor"></a>
2. Preparing Django project files
</h3>
_For those who have cloned repo need not require to do any changes to the django files and can skip this step 2, but for others who are deploying their own django project shall continue with below steps:_

If you are deploying your own django application then make sure to allow all hosts by Changing ALLOWED_HOSTS in your django settings file as shown below. (Not recommended for security reasons, eventually we want to change this to an IP)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/709t1h3vhoyqswaa4ome.jpg)

Make sure you have requirements.txt file for installing required dependencies.


<h3>
<a name="3" href="#3" class="anchor"></a>
3. Create yaml files to automate AWS CI-CD
</h3>

For this basic tutorial we will create 3 files appspec.yml, before_install.sh & after_install.sh to automate the deployment process handled by AWS CI-CD.

Folder/file structure:

![Folder/file structure](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c4kjwjg33b9vs224wqxt.jpg)

Create appspec.yml file inside your root project directory where manage.py file is.

> Step 1: Create CodeDeploy appspec.yml file    

```
version: 0.0
os: linux
files:
  - source: /
    destination: /home/ubuntu/django-aws_cicd
hooks:
  BeforeInstall:
      - location: scripts/before_install.sh
  AfterInstall:
      - location: scripts/after_install.sh
```

> Step 2: Create before_install.sh file

```
#!/usr/bin/env bash

# clean codedeploy-agent files for a fresh install
sudo rm -rf /home/ubuntu/install

# install CodeDeploy agent
sudo apt-get -y update
sudo apt-get -y install ruby
sudo apt-get -y install wget
cd /home/ubuntu
wget https://aws-codedeploy-us-east-1.s3.amazonaws.com/latest/install
sudo chmod +x ./install 
sudo ./install auto

# update os & install python3
sudo apt-get update
sudo apt-get install -y python3 python3-dev python3-pip python3-venv
pip install --user --upgrade virtualenv

# delete app
sudo rm -rf /home/ubuntu/django-aws_cicd
```
`vi scripts/after_install.sh`

> Step 3: Create after_install.sh file

```
#!/usr/bin/env bash

# kill any servers that may be running in the background 
sudo pkill -f runserver

# kill frontend servers if you are deploying frontend
# sudo pkill -f tailwind
# sudo pkill -f node

cd /home/ubuntu/django-aws_cicd/

# activate virtual environment
python3 -m venv venv
source venv/bin/activate

install requirements.txt
pip install -r /home/ubuntu/django-aws_cicd/requirements.txt

# run server
screen -d -m python3 manage.py runserver 0:8000
```
Before we start setting up AWS CI-CD we need to ensure all changes made locally inside django files are pushed to github.

<h2>
<a name="8" href="#8" class="anchor"></a>
AWS CI-CD Configuration:
</h2>

Let's get started configuring AWS for CI-CD pipeline, for this we are going to be using 3 services mainly IAM roles, CodeDeploy & CodePipeline.

<h3>
<a name="4" href="#4" class="anchor"></a>
4. Create roles in AWS
</h3>


We want to create 2 IAM roles:

**AmazonEC2RoleforAWSCodeDeploy** provides EC2 access to S3 bucket to download revision:

Step 1: Choose AWS Service & EC2 for Common use cases and click Next
Step 2: Search & select `AmazonEC2RoleforAWSCodeDeploy` and click Next
Step 3: Provide a custom role name and click Create role, in my case the role name is _EC2CodeDeployRole_


**AWSCodeDeployRole** for CodeDeploy service access to expand tags and interact with Auto Scaling on your behalf.

Step 1: Choose AWS Service & in the 'Use cases for other AWS services' drop down choose CodeDeploy and click Next
Step 2: `AWSCodeDeployRole` will be the policy on display, click Next
Step 3: Provide a custom role name and click Create role, in my case the role name is _CodeDeployRole_

<h3>
<a name="5" href="#5" class="anchor"></a>
5. Launching EC2 instance with AWS CodeDeploy configuration
</h3>

When launching a new EC2 instance ensure to add `AmazonEC2RoleforAWSCodeDeploy` IAM role that we created and add user data for CodeDeploy agent installation.


![ec2_1](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7hfztt07a2xb7i760fqt.jpg)

![ec2_2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3narzdci06e4wzkrxhdi.jpg)

```
#!/usr/bin/env bash
sudo apt-get -y update
sudo apt-get -y install ruby
sudo apt-get -y install wget
cd /home/ubuntu
wget https://aws-codedeploy-us-east-1.s3.amazonaws.com/latest/install
sudo chmod +x ./install 
sudo ./install auto

```
You must provide a name to your instance if you had not provided when creating an instance, instance name will be required when creating CodeDeploy deployment group in upcoming steps.

![ec2_3](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x3om4u5nt9icmzi1teip.jpg)

Configure Security group attached to EC2 to allow port 8000:

![sg_1](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mnseaptlwoyvhlxnenff.jpg)

Once you launch your instance wait for few minutes for status checks to be completed.

<h3>
<a name="6" href="#6" class="anchor"></a>
6. Configure AWS Code Deploy
</h3>

For creating CodeDeploy we first need to create application and then create deployment group, steps below:

> Step 1: Search for CodeDeploy service in AWS
![cd_1](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nupmb2g9107eh31hwskz.jpg)
Step 2: On the left navigation panel open Deploy -> Select **Applications** and then click on **Create application**
![cd_2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jjw9den52zsaktl1crdi.jpg)
Step 3: Provide any application name of your choice, for Compute Platform choose **EC2/On-premises** from the drop down and then click on **Create application**
![cd_3](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nutlo1dgemfy7cf0ve8v.jpg)
Step 4: Will be redirected inside application that we just created, now click on **Create deployment group**
![cd_4](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6g1m9911arj20ij9n3ea.jpg)
Step 5: Enter a deployment group name of your choice and then choose the service role that we created for CodeDeploy, in this tutorial we named it **CodeDeployRole**
![cd_5](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fl1vprlk8bbr7xxjzd2u.jpg)
Step 6: Environment configuration choose **Amazon EC2 instances** and then add the ec2 instance we created, for **Key** choose **Name** and for **Value** choose <EC2 instance name> in this tutorial we named the instance **aws-cicd**.
![cd_6](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oc6m9wpcshd6nl7mw1ce.jpg)
Step 7: Uncheck the **Enable load balancing** and then click on **Create deployment group**.
![cd_7](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/boz2wyxi2k1ekrt9r295.jpg)

<h3>
<a name="7" href="#7" class="anchor"></a>
7. Configure AWS Code Pipeline
</h3>

CodePipeline brings everything together to build the final CI-CD

Initial Step: On left navigation panel open **Pipeline** then click on **Pipelines** and finally click on **Create Pipeline**
![cp_1](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f2vx3j9gmnl7vekggrfb.jpg)
Step 1: Enter a pipeline name of your choice, a role name gets automatically created for you, now click **Next**

![cp_2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/agwb86ft7g585go8gxll.jpg)
![cp_3](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x1qsmhrbrvelm8vwzp1a.jpg)
Step 2: From the drop down choose **GitHub (Version 2)**, click on **Connect to GitHub**, once you have a successful connection choose Repository name, branch name and then click **Next**

![cp_4](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9wv2afz83c961dskztjr.jpg)
![cp_5](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8jc5havj9j8k7x3enbvm.jpg)
![cp_6](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k2us7uh5iwqlqbzaas4h.jpg)
![cp_7](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bl787l97d5gof5k4ka2a.jpg)
Step 3:
Build is out of scope for this tutorial, click on **Skip build stage**
![cp_8](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nzbns6hucr1hrh663q1n.jpg)
Step 4: From **Deploy provider** drop downs choose **AWS CodeDeploy**, choose the application name and deployment group that we created from step 6 and then click **Next**.
![cp_9](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g0dpwdqvvdnoq0v9v0dt.jpg)
Step 5: Review the page, scroll down to the bottom of the page and then click on **Create pipeline**
![cp_10](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j8kf99padeh4374b0ma1.jpg)

We have completed setting up and creating CI-CD pipeline on AWS, we can check the progress either by clicking on the **Details** in **Deploy** section or in the left panel **Deployments**, then scroll down and click on **View events** to see the status of deployment.
![cp_12](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lzr9g2xkdmw5qx4pisi5.jpg)
![cp_13](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lbgd95own6vkq0g57ggx.jpg)
![cp_14](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/enzicokbisakglxtuaoq.jpg)

## Run Application:

Go to EC2 instance, copy the **Public IPv4 DNS**

![cp_15](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ml6s407ib997qbrkud8h.jpg)

navigate using this url:

```
http://<Public IPv4 DNS>:8000
```
You should see this django app running...

![success](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jy3lzvsymi9rlo1l4ree.jpg)

## Contributors