How to deploy a Django App on Heroku in less than 5 minutes

jonatanvm

Jonatan

Posted on October 2, 2021

How to deploy a Django App on Heroku in less than 5 minutes

In this short tutorial, I will demonstrate how to deploy a Django project on Heroku while serving static files from your own domain.

Prerequisites:

You do not need to use virtualenv, but it is highly recommended to use an isolated environment for different projects. Another option to virtualenv, for deploying to Heroku, is pipenv.

Installing Django, virtualenv, pip and the heroku-cli on Ubuntu

sudo apt install python3
sudo apt install python3-django
sudo apt install python3-virtualenv
sudo apt install python3-pip
sudo snap install --classic heroku
Enter fullscreen mode Exit fullscreen mode

Creating a Django project

We can now create our Django project named myproject

django-admin startproject myproject
Enter fullscreen mode Exit fullscreen mode

Setting up your virtual environment

You now want to go to the root of your project and set up your virtual environment.

Navigate to your project

cd myproject
Enter fullscreen mode Exit fullscreen mode

Make a virtual environment

virtualenv venv
Enter fullscreen mode Exit fullscreen mode

Activate your virtual environment

source venv/bin/activate
Enter fullscreen mode Exit fullscreen mode

Install Django in your virtual environment

pip install django
Enter fullscreen mode Exit fullscreen mode

Creating a new Heroku project

We now want to create a new Heroku project.

heroku create
Enter fullscreen mode Exit fullscreen mode

This will create a domain at https://example.herokuapp.com so select the project name to be the domain you want your project to be hosted at. (You can later add a custom domain).

Changing the secret key

First, we want to change the SECRET_KEY to an environment variable, because we want to have a unique SECRET_KEY in production that we don't push to version control.

SECRET_KEY = os.getenv('SECRET_KEY', 'change-in-production')
Enter fullscreen mode Exit fullscreen mode

Now we can set our production environment variable with

heroku config:set SECRET_KEY=very-long-secret-key
Enter fullscreen mode Exit fullscreen mode

We now need to set up static files and turn off DEBUG mode in production.

Setting up static files

We are going to use whitenoise to serve static files. First, we need to install it

pip install whitenoise
Enter fullscreen mode Exit fullscreen mode

Next, we add the whitenoise middleware to the top of the middleware section

MIDDLEWARE = [
    'whitenoise.middleware.WhiteNoiseMiddleware', # First in list
    ...
]
Enter fullscreen mode Exit fullscreen mode

Next, we set up the path of our static files

STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
Enter fullscreen mode Exit fullscreen mode

We then install django_heroku to configure default values.

pip install django_heroku
Enter fullscreen mode Exit fullscreen mode

We enable the django_heroku settings, but set staticfiles and allowed_hosts to False, because we want to specify our own static file options and change allowed_hosts from the django_heroku default value ['*'] to prevent Host Header attacks.

django_heroku.settings(locals(), staticfiles=False, allowed_hosts=False)
Enter fullscreen mode Exit fullscreen mode

At the bottom of the settings.py file, we will now add settings specific to Heroku.

if "DYNO" in os.environ:
    STATIC_ROOT = 'static'
Enter fullscreen mode Exit fullscreen mode

Initializing git

We will now add git to our project.

git init
Enter fullscreen mode Exit fullscreen mode

Adding Heroku to your git remotes

heroku git:remote -a example
Enter fullscreen mode Exit fullscreen mode

Disabling DEBUG and settings allowed hosts

We now want to disable DEBUG in production and add our domain to our allowed hosts. We add these options in the if "DYNO" in os.environ block because we only want these settings to be in effect in production.

if "DYNO" in os.environ:
    STATIC_ROOT = 'static'
    ALLOWED_HOSTS = ['example.herokuapp.com']
    DEBUG = False
Enter fullscreen mode Exit fullscreen mode

Adding the Procfile

First, we will add the Procfile. To do this just add a file called Procfile (without any extension) to the root of your project. On ubuntu and mac simply write

touch Procfile
Enter fullscreen mode Exit fullscreen mode

We then install gunicorn which is the HTTP server we use in production on Heroku.

pip install gunicorn
Enter fullscreen mode Exit fullscreen mode

while in the terminal while in the root directory. Next, add the following to the file

web: gunicorn myproject.wsgi --log-file -
Enter fullscreen mode Exit fullscreen mode

Adding the requirements.txt file

Our last step is to create the requirements.txt file, which will specify all the packages that we have used. Since we used a virtual environment, this step is very easy. All we have to do is type

pip freeze > requirements.txt
Enter fullscreen mode Exit fullscreen mode

in the terminal while being in our projects root directory. This will add all our packages installed through pip to the requirements.txt file automatically.

If you weren't using a virtual environment, you can also manually create a requirements.txt file in the root directory and manually add all the requirements. If you did everything correctly your requirements.txt file should look like

asgiref==3.4.1
dj-database-url==0.5.0
Django==3.2.7
django-heroku==0.3.1
gunicorn==20.1.0
psycopg2==2.9.1
pytz==2021.1
sqlparse==0.4.2
whitenoise==5.3.0
Enter fullscreen mode Exit fullscreen mode

Deploying to Heroku

We are now ready to deploy our project.

git add .
git commit -m "My first project is ready to be deplayed"
git push heroku main
Enter fullscreen mode Exit fullscreen mode

And we are done! Your project is now deployed to Heroku.

Optional settings for production

If you want to make sure your project only works over https you want to add the following options to your production settings.

if "DYNO" in os.environ:
    STATIC_ROOT = 'static'
    ALLOWED_HOSTS = ['example.herokuapp.com']
    DEBUG = False
    SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
    SECURE_SSL_REDIRECT = True
    SESSION_COOKIE_SECURE = True
    CSRF_COOKIE_SECURE = True
Enter fullscreen mode Exit fullscreen mode
  • CSRF_COOKIE_SECURE  -  Ensures your CSRF cookies will be served over https.
  • SESSION_COOKIE_SECURE  -  Ensures your session cookies will be served over https.
  • SECURE_PROXY_SSL_HEADER & SECURE_SSL_REDIRECT  -  Will redirect all HTTP traffic to https

Additional reading

💖 💪 🙅 🚩
jonatanvm
Jonatan

Posted on October 2, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related