Django Setup with GitLab and Heroku
tutorial coding django heroku gitlabcreate a Django app with GitLab CI/CD and deploy automatically to Heroku.
Article Index
update: this guide is outdated and archived. Heroku phased out their free tier on the 28th of November, 2022.
start by creating a git repository and a new heroku app. inside your GitLab project settings, under CI/CD variables, add three keys: HEROKU_APIKEY
, HEROKU_APPNAME
, and HEROKU_APP_HOST
. these will be used to connect GitLab’s pipeline with your Heroku deployment.
initialize and add your remote origin and Heroku remotes:
git init
git remote add origin https://gitlab.com/username/git-repo-name.git
heroku git:remote -a heroku-appname
with that ready, add a .gitlab-ci.yml
file to enable pipelines. you’ll also need a simple script for migrations:
deployment.sh #!/bin/bash
python manage.py makemigrations
python manage.py migrate
Heroku also requires a Procfile
in your project’s root. this file specifies how your app runs:
Procfile migrate: bash deployment.sh
web: gunicorn your_project_name.wsgi
note that Procfile
must not have an extension. it explicitly declares process types for Heroku, and without it your deployment won’t know what to run. if you need more details, see heroku’s docs on procfile. before committing, make sure to grab a proper Python .gitignore
to avoid pushing unnecessary files.
virtual environment
update: do not use virtualenv anymore. use
uv
,pipenv
, orpoetry
instead.
using a virtual environment is essential to make sure your global Python installation won’t get cluttered with libraries from every project. start by installing Python 3 and ensuring it’s available in your PATH
. install virtualenv with pip:
pip install virtualenv
on Windows, virtualenvwrapper-win makes environment management easier:
pip install virtualenvwrapper-win
to create an environment:
mkvirtualenv your-env-name
activate it with workon your-env-name
, or list all environments simply with workon
. once inside, add a requirements.txt
file listing your dependencies:
requirements.txt Django==2.1.1
gunicorn==19.7.1
whitenoise==3.3.0
dj-database-url==0.4.2
psycopg2==2.7.5
requests==2.18.4
# and so on...
install everything with:
pip install -r requirements.txt
if a library like psycopg2
fails, remove it temporarily from the file, install the rest, then install that library separately. afterwards, regenerate your requirements file with pip freeze > requirements.txt
.
Django setup
create your django project and app:
django-admin startproject your_project_name
django-admin startapp your_app_name
open project/settings.py
and update it:
project/settings.py import os
import dj_database_url
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
PRODUCTION = os.environ.get('DATABASE_URL') is not None
ALLOWED_HOSTS = ['*']
INSTALLED_APPS = [
...
'your_app_name',
]
MIDDLEWARE = [
...
'whitenoise.middleware.WhiteNoiseMiddleware',
]
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
this configuration allows Heroku deployments to work correctly. if DATABASE_URL
is present, Heroku’s environment will override your database settings:
project/settings.py#92 if PRODUCTION:
DATABASES['default'] = dj_database_url.config()
you’ll also want to configure static files:
project/settings.py#130 PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__))
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'assets')
]
STATIC_ROOT = os.path.dirname(os.path.abspath(__file__))
STATIC_URL = '/static/'
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
this ensures CSS, JS, and images are collected and served properly in production.
finally, wire up your app’s urls and views:
project/urls.py from django.contrib import admin
from django.urls import include, path
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('app_name.urls')),
]
and inside your app, define urls and views:
project/urls.py from django.urls import path
from .views import *
urlpatterns = [
path('', home, name='home'),
]
project/views.py from django.shortcuts import render
def home(request):
return render(request, 'your_template.html')
place your templates (.html
files) inside a templates
directory within your app, and you’re ready to run locally or deploy. from here on, pushing to GitLab will trigger the pipeline, migrations will run, and your Django project will be live on Heroku.