Published on

Deploying a Django app to DigitalOcean using GitHub Actions, Terraform and Ansible - Part 1

Authors

This series will guide you through deploying a Django application to DigitalOcean using a trio of complementary tools:
Terraform for infrastructure provisioning, Ansible for configuration management, and GitHub Actions for automation orchestration.

  • DigitalOcean is a cloud hosting provider that offers self-serve infrastructure for hosting web applications. This includes virtual machines called Droplets, managed Relational Database and Load Balancer.

  • Terraform allows you to define your desired infrastructure resources (servers, databases, etc.) in code, and provision those resources on IaaS provider such as DigitalOcean.

  • Ansible is a configuration management tool that automates software setup, configuration, and deployments.

  • GitHub Actions enables you to modify your infrastructure and deploy updates to your application automatically on code pushes.

Part 1: Setting Up the Django Project

This part explains how to create a starter Django project, configure settings from environment variables and host the code on Github.

Part 2: Provisioning Infrastructure on DigitalOcean using Terraform and Github Actions

This part guides you through provisioning the required infrastructure on Digital Ocean

Part 3: Ansible for Application Deployment Automation

This part explains how to use Ansible to automate the deployment process.

Step 1 - Creating a starter Django project

Create a directory named django-on-digitalocean and navigate to it

mkdir django-on-digitalocean && cd django-on-digitalocean

Create a src directory which will contain the Django/Python application code.

mkdir src

Confirm the contents of your top level folder is as expected:

ls -F
src/

Navigate to the src folder

cd src

Then create a python virtual enviroment to isolate the Python project dependencies

python -m venv venv

Activate the Python virtual environment

source venv/bin/activate

Create a direcotry named myproject and navigate to it

mkdir myproject && cd myproject

Create a requirements.txt file with the following content

# django-on-digitalocean/src/myproject/requirements.txt
Django==5.0
django-environ==0.10.0
  • django-environ is used to read application settings from the environment. This will allow the application to use different settings depending on whether it is running locally or deployed to DigitalOcean

Install the Python dependencies

 pip install -r requirements.txt

Then create a starter Django project using the django-admin tool

django-admin startproject myproject .

Confirm that the contents of the top level Django folder are as expected by running this command

ls -F
manage.py*		myproject/		requirements.txt

Confirm the contents of myproject folder are as expected:

ls -F myproject
__init__.py	asgi.py		settings.py	urls.py		wsgi.py

Rename the default generated settings.py file to basesettings.py

mv myproject/settings.py myproject/basesettings.py

Create a new settings.py file

touch myproject/settings.py

And add the following Python code to myproject/settings.py.

import io
import os
from urllib.parse import urlparse

import environ


from .basesettings import *


env = environ.Env(DEBUG=(bool, False))
env_file = os.path.join(BASE_DIR, ".env")

if os.path.isfile(env_file):
    # Use a local secret file, if provided
    env.read_env(env_file)
else:
    raise Exception("No local .env found.")

SECRET_KEY = env("SECRET_KEY")
DEBUG = env("DEBUG", default=False)
DATABASES = {"default": env.db()}

Create a .env file in the Django project root folder with the following content

# django-on-digitalocean/src/myyproject/.env
SECRET_KEY="django-insecure-secret-key"
DATABASE_URL=sqlite:////tmp/db.sqlite3
DEBUG=on

Step 2 - Running the application locally

Initialize the sqlite database by running this command

python manage.py migrate

You should see output similar to this if migrations are run successfully

Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying admin.0003_logentry_add_action_flag_choices... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying auth.0009_alter_user_last_name_max_length... OK
  Applying auth.0010_alter_group_name_max_length... OK
  Applying auth.0011_update_proxy_permissions... OK
  Applying auth.0012_alter_user_first_name_max_length... OK
  Applying sessions.0001_initial... OK

Create a superuser account for logging into the Django admin interface

python manage.py createsuperuser --username admin --email admin@example.com

When prompted enter a password of your choice and confirm

Password:
Password (again):
Superuser created successfully.

Run the developement server

python manage.py runserver

The server starts up and prints output similar to this:

Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).
January 01, 2024 - 08:32:11
Django version 5.0, using settings 'django_cloudrun.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

Navigate to http://127.0.0.1:8000 in your web browser and you will see the Django welcome page

Navigate to the Django admin site http://127.0.0.1:8000/admin and login using the admin username and the superuser password you set.

The Django admin dashboard is displayed

Step 3 - Creating the Github repository

Navigate to the top level django-on-digitalocean folder then add a .gitignore file

touch .gitignore

Copy then content from this gitignore Github repository into the .gitignore file

Create a repository on Github named django-on-digitalocean

Then initialize a new Git repository in your top level folder and push your code to Github by typing this commands

git init
git add .
git commit -m "first commit"
git remote add origin git@github.com:yourgithubusername/django-on-digitalocean.git
git push -u origin main

Part 2 will explain how to provision the required infrastructure on DigitalOcean using Terraform and GitHub Actions