This is a boilerplate repo intended for quickly starting a new Django project with PostgreSQL and Redis support, all running within Docker containers.
Multiple production hosting options are also included. See the Production Hosting section below for more information.
pipenv install
to set up libraries locally for the editor to crawl. The Django container also uses Pipenv to install dependencies to encourage use of this new Python package management tool.rm -rf .git/
git init
git add .
git commit -m "Initial Commit"
pipenv install --three
pipenv run django-admin startproject appname _app/
# appname/settings.py
import os
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = os.getenv('DJANGO_SECRET_KEY')
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = os.getenv('DEBUG', False) == 'true'
# Enable traffic and form submissions from localhost and PROD_HOST_NAME
ALLOWED_HOSTS = ['localhost']
CSRF_TRUSTED_ORIGINS = ['http://localhost']
PROD_HOST_NAME = os.getenv('PROD_HOST_NAME', None)
if PROD_HOST_NAME:
ALLOWED_HOSTS.append(PROD_HOST_NAME)
CSRF_TRUSTED_ORIGINS.append(f'https://{PROD_HOST_NAME}')
# Configure whitenoise for static file hosting
INSTALLED_APPS = [
# ...
# See http://whitenoise.evans.io/en/latest/django.html#using-whitenoise-in-development
"whitenoise.runserver_nostatic",
"django.contrib.staticfiles",
# ...
]
MIDDLEWARE = [
# ...
"django.middleware.security.SecurityMiddleware",
# See http://whitenoise.evans.io/en/latest/django.html#enable-whitenoise
"whitenoise.middleware.WhiteNoiseMiddleware",
# ...
]
# Point Django to Docker-hosted Postgres
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': os.getenv('POSTGRES_USER'),
'USER': os.getenv('POSTGRES_USER'),
'PASSWORD': os.getenv('POSTGRES_PASSWORD'),
'HOST': 'db',
'PORT': 5432,
}
}
# Set up static files
STATIC_ROOT = 'static'
# See http://whitenoise.evans.io/en/latest/django.html#enable-whitenoise
STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage"
# Redis cache support
# https://docs.djangoproject.com/en/4.0/topics/cache/#redis-1
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.redis.RedisCache',
'LOCATION': 'redis://redis:6379/1',
}
}
SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
SESSION_CACHE_ALIAS = 'default'
docker compose up
Builds the Django container. The container is built from a standard python Docker image and will run Django's colletstatic
when being built.
Use ./start-dev.sh
to start Django for development. This will spin up three containers: the above container for Django, one for PostgreSQL, and one for Redis.
Django can be accessed in DEBUG mode directly from http://localhost:8000 during development. The Gunicorn workers are set to reload when file changes are detected.
Postgres can also be directly accessed at localhost:5432
using the credentials you specified in the .env file.
See the Production Hosting section below for more information.
Use ./start-dev.sh
to start Django for production. You can also run ./update-prod-django.sh
whenever you need to deploy a new build.
Includes Python packages needed to make Django, Postgre, and Redis work together.
Contains environment variables for the containers. Several variables are included for configuring Postgres and Django secrets.
Defines files that Docker should never include when building the Django image.
Defines some common settings to help ensure consistency of styling across files.
Configures the flake8 Python linter. Includes a few common settings to my personal preferences.
Helps configure the Python plugin to lint with flake8. A placeholder Python interpreter setting is left in to simplify pointing to the local virtual environment created with Pipenv.
Defines settings for gunicorn, including a port binding, workers, and a gunicorn-specific error log.
Establishes a reverse-proxy to Django, and serves Django static files using Caddy. See Production Hosting below for more info.
This project includes two options for handling production hosting, including reverse-proxying Django and handling SSL:
You'll only need one of these! Which ever option you choose below, delete the other commented-out service in docker-compose.prod.yml.
Follow these steps:
caddy
service in docker-compose.prod.ymlvolumes
in docker-compose.prod.ymlstatic_files_volume:...
entry in django
service's volumes
property in docker-compose.prod.ymlWhen these steps are complete, running start-prod.sh should make Django available on the public internet at https://$PROD_HOST_NAME
.
Uncomment the cloudflaretunnel
service in docker-compose.prod.yml and then follow these steps:
--token
flag in the page's docker
command to this project's .env file as the CLOUDFLARE_TUNNEL_TOKEN
environment variablePROD_HOST_NAME
variable in the .env file to the tunnel's configured Public hostnameWhen these steps are complete, running start-prod.sh should make Django available on the public internet at https://$PROD_HOST_NAME
. No firewall ports need to be opened on the production host, and in fact you may wish to set up the firewall to block all incoming traffic for good measure.
You probably forgot to replace the string "appname" with the actual name you passed to django-admin startproject
. Check _app/gunicorn_appname.log to see if Gunicorn is erroring out with something like this:
ModuleNotFoundError: No module named 'appname'