Back to Blog
Jan 1, 20258 min read

Github Actions CI/CD Pipeline: Deploy Dockeriz Django on AWS EC2 with PostgreSQL, Celery…

DockerAWSKubernetesDjangoDevOps
Github Actions CI/CD Pipeline: Deploy Dockeriz Django on AWS EC2 with PostgreSQL, Celery…

If you are not a Medium Member and want to read Free, You can read on My Linkedin.

I Will make sure 100% you get it done perfectly and successfully.💪🚀🔥

In today’s fast-paced development environment, efficient deployment practices are essential for ensuring that your applications run smoothly and scale effortlessly.

If you’re a developer looking to streamline your deployment process, this guide is for you. I’ll take you through the complete journey of deploying a Dockerized Django backend on an AWS EC2 instance, setting up Nginx as a reverse proxy, and automating the entire process with a powerful CI/CD pipeline using GitHub Actions. By the end of this tutorial, you’ll have a robust and scalable backend setup that can be updated effortlessly with every push to your repository. Whether you’re new to AWS, Docker, or CI/CD, this guide will walk you through the essential steps to take your deployment workflow to the next level. Let’s dive in!

Table of contents:

  1. Prepare your Project Locally for Production Ready
  2. AWS EC2 Instance Creation
  3. Install necessary Packages on EC2
  4. Clone your Project on EC2
  5. Nginx Setup
  6. CI/CD Pipeline Setup with Github Actions: Automate Deployment
  7. Conclusion

YouTube Video: I recommend watching the video to get the most out of this article.

1. Prepare Your Project Locally for Production

Before you begin, make sure Docker Desktop is installed and running on your system. You can download it from

Next, you have two options for your project setup:

git clone https://github.com/codewithmuh/deploy-dockerize-django-ec2.git

If you prefer to use your repo, you’ll need to copy a few essential files and folders from my repo to yours:

After copying these, you’ll also need to update some of your own project files:

  • settings.py
  • urls.py (located in your core folder where settings.py resides)
  • requirements.txt — Ensure you include all the packages listed in my requirements.txt.

For full details on the changes required in settings.py, urls.py, and other files, check out the video for further explanations.

2. Test Your Project Locally

Once you’ve set up your project, it’s time to run it locally. Execute the following command:

docker compose -f "./build-process/docker-compose-django-backend.yml" up -d --build

This will build all your Docker images and containers. Once everything is up and running, you should see confirmation that the containers are healthy.

if all is good, Push your code on github. You are done with your project configuration setup.

2. AWS EC2 Instance Creation

Watch my video for this section if you do not know how to create AWS EC2 instance.

Before starting, ensure you have an AWS EC2 instance up and running. Make sure it’s configured with sufficient resources based on your project needs. Also, Attach Elastic IP to your instance.

3. Necessary Packages Installation on AWS EC2

# Updates the package index to ensure you have the latest information about #available packages.
sudo apt-get update -y

# Installs the Nginx web server with a confirmation flag (-y) to bypass the prompt.
sudo apt install nginx -y

# Installs Docker from the default Ubuntu package repository.
sudo apt install docker.io -y

# Adds the 'ubuntu' user to the 'docker' group, allowing the user to run Docker #commands without sudo.
sudo usermod -aG docker ubuntu

# Activates the changes made to the user group without requiring a system reboot.
newgrp docker

# Sets read, write, and execute permissions for all users on the Docker socket file 
sudo chmod 777 /var/run/docker.sock

# Downloads the latest version of Docker Compose and saves it to #/usr/local/bin/docker-compose.

sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose


# Makes the Docker Compose binary executable.
sudo chmod +x /usr/local/bin/docker-compose

# Verifies the installation of Docker Compose by displaying its version.
docker-compose --version 

4. Clone your Project on EC2

It will ask you for your GitHub username:

Then Password. You can create a password

Settings-> Developer Settings -> Token>

save the token somewhere, and use it as a password whenever needed.

Watch My Video to clone the Private repo.

Go to the Project directory

Now run this command to start all services.

sudo docker-compose -f "./build-process/docker-compose-django-backend.yml" up -d --build # if above command does not work use docker compose -f "./build-process/docker-compose-django-backend.yml" up -d --build

or 
sudo docker compose -f "./build-process/docker-compose-django-backend.yml" up -d --build # if above command does not work use docker compose -f "./build-process/docker-compose-django-backend.yml" up -d --build

Now you can check if all docker containers are running and up successfully.

Setup nginx, so you can access your application at ec2 ip address.

First, with this command, you can check if already a default nginx file exists. You have to remove it.

cd /etc/nginx/sites-enabled/ sudo rm -rf default

Create a configuration file for Nginx using the following command

sudo vim /etc/nginx/sites-available/<nginx-file-name>

Paste the below contents inside the file created

# Backend Nginx Config
server {
    listen 80;
    server_name _;



    # Serve favicon.ico directly from Nginx to avoid logging and not_found errors
    location = /favicon.ico {
        access_log off;
        log_not_found off;
    }

    # Serve static files directly from Nginx
    location /static/ {
        alias /home/ubuntu/codewithmuh-backend/app-content/static_root/;
    }

    # Serve media files directly from Nginx
    location /media/ {
        alias /home/ubuntu/codewithmuh-backend/app-content/media_root/;
    }

    # Serve template files directly from Nginx
    location /templates/ {
        root /home/ubuntu/codewithmuh-backend/app-content;
    }

    # Proxy other requests to the Django app running on Docker
    location / {
        include proxy_params;
        proxy_pass http://<YOUR-EC2-IP-ADDRESS>:8080;
        # Set X-Forwarded-Protocol header
        proxy_set_header X-Forwarded-Protocol $scheme;
    }

    # Set maximum allowed body size for client requests
    client_max_body_size 134217728;
} 

Activate the configuration using the following command:

sudo ln -s /etc/nginx/sites-available/<nginx-file-name> /etc/nginx/sites-enabled/

Run this command to load a static file. username in my case is ubuntu. if you are using aws ec2 ubuntu, it will ubuntu.

$ sudo gpasswd -a www-data <username>

Restart Nginx and allow the changes to take place.

sudo systemctl restart nginx sudo service nginx restart

Additionally in case of errors

$ sudo tail -f /var/log/nginx/error.log

To check if nginx is working fine

$ sudo systemctl status nginx

Next, we have to automate the deployment, next time when we push code to Git Hub, it should be auto-deployed on aws ec2. Let’s do it now.

6. CI/CD Pipeline Setup with Github Actions: Automate Deployment

Now Go to GitHub Repository and click on Settings -> Actions -> Runners

Click on New self-hosted runner

Now select Linux and Architecture X64

Use the below commands to add a self-hosted runner

Note: In the pic, Commands are related to my account, Use your commands, and they will appear on your GitHub self-hosted runner Page.

Now SSH to your AWS instance to connect with your Instance.

And Past/Run these commands.

mkdir actions-runner && cd actions-run

Command “mkdir actions-runner && cd actions-runner” serves to generate a fresh directory named “actions-runner” within the present working directory. Subsequently, it swiftly switches the current working directory to this newly created “actions-runner” directory. This approach streamlines file organization and facilitates executing successive actions within the newly formed directory without the need for separate navigation.

Download the latest runner package

curl -o actions-runner-linux-x64-2.311.0.tar.gz -L https://github.com/actions/runner/releases/download/v2.311.0/actions-runner-linux-x64-2.311.0.tar.gz
echo "29fc8cf2dab4c195bb147384e7e2c94cfd4d4022c793b346a6175435265aa278 actions-runner-linux-x64-2.311.0.tar.gz" | shasum -a 256 -c

Now Extract the installer

tar xzf ./actions-runner-linux-x64-2.311.0.tar.gz

Create the runner and start the configuration experience

./config.sh --url https://github.com/codewithmuh/react-aws-eks-github-actions --token AMFXNTP3IVE6IAZSWO3ZEGDFT2QV6

If you have provided multiple labels use commas for each label.

Create systemd Service File on EC2.

sudo nano /etc/systemd/system/run-script.service
[Unit] Description=Script Runner Service After=network.target [Service] Type=simple Restart=always User=ubuntu WorkingDirectory=/home/ubuntu/actions-runner ExecStart=/home/ubuntu/actions-runner/run.sh [Install] WantedBy=multi-user.target
sudo systemctl daemon-reload sudo systemctl enable run-script sudo systemctl start run-script sudo systemctl status run-script

Create a file in your Project

‘.github/workflows/cicd.yml’

and then past the content there.

Then Change The Project Name: <Project-Name> Replace with yours.

then push the changes to your main branch via a PR request from feature branch.

name: Deployment to AWS EC2 on: push: branches: - main pull_request: types: [closed] jobs: deploy: if: github.event_name == 'push' && github.ref == 'refs/heads/main' runs-on: self-hosted steps: - name: Check out code uses: actions/checkout@v2 - name: Build and Deploy run: | cd /home/ubuntu/deploy-dockerize-django-ec2 git checkout maij git pull origin staging sudo docker-compose -f "./build-process/docker-compose-django-backend.yml" up -d --build sudo docker exec backend-django-production python manage.py migrate sudo service nginx restart

now you can make changes and push code, you will see successful auto deployment.

if you enjoyed this article, be sure to:

  • Clap and Comment to share your thoughts 💬
  • Follow me for more insights on LinkedIn, Youtube, and GitHub

Stay connected on YouTube | Medium | GitHub

💬 Got questions? Ask me anything!