Python Quickstart Guides

Django Quickstart Guide

This guide will show you how to set up a Python App using the Django framework, Gunicorn, and PostgreSQL.

Create an App

Tell Aptible that you want to provision an App. Until you push code and trigger a build, Aptible uses this as a placeholder.

To create an App, use the Dashboard, or the aptible apps:create command:

# Set or substitute $APP_HANDLE with the app name of your choice

aptible apps:create "$APP_HANDLE"

Aptible will provide your App's Git Remote in return. Copy it, you'll need it later.

Going forward in this document, we'll refer to the App's handle as $APP_HANDLE, and its Remote as $GIT_REMOTE.

Provision a Database

Start by adding a PostgreSQL Database for your App:

aptible db:create "$DB_HANDLE" --type postgresql

Make sure you set or substitute $DB_HANDLE with the database name of your choice (alternatively, you could use the Dashboard to create a Database as well).

The aptible db:create will return a connection string on success. This is a Database Credential. You'll need it later to configure your App.

Going forward in this document, we'll refer to the Credential as $DATABASE_URL.



Databases are only reachable from within your Stack's internal network.

This means your Containers will be able to connect to your database, but if you want to connect from your workstation, you'll need to use a Database Tunnel.

Add a Dockerfile

The Dockerfile is a text file that contains the commands you would otherwise execute manually to build a Docker image. Aptible uses the resulting Image to run Containers for your App.

A few guidelines:

  1. The file needs to be called Dockerfile, starting with a capital letter, and no extension.
  2. Place the Dockerfile at the root of the repository.
  3. Be sure to commit them to version control.

Here is a sample Dockerfile for a Django App:



In the below Dockerfile, you must update the WSGI module name (mysite.wsgi) passed to Gunicorn to match your app's!

FROM python:3.6

# System prerequisites
RUN apt-get update \
 && apt-get -y install build-essential libpq-dev \
 && rm -rf /var/lib/apt/lists/*

# If you require additional OS dependencies, install them here:
# RUN apt-get update \
#  && apt-get -y install imagemagick nodejs \
#  && rm -rf /var/lib/apt/lists/*

# Install Gunicorn. If Gunicorn is already present in your requirements.txt,
# you don't need that (but if won't hurt).
RUN pip install gunicorn

ADD requirements.txt /app/
RUN pip install -r requirements.txt

ADD . /app

# Collect assets. This approach is not fully production-ready, but
# will help you experiment with Aptible before bothering with static
# files.
# Review for production-ready advice.
RUN set -a \
 && . ./.aptible.env \
 && python collectstatic


CMD ["gunicorn", "--access-logfile=-", "--error-logfile=-", "--bind=", "--workers=3", "mysite.wsgi"]



See Optimizing Dockerfile caching for pip to better understand this Dockerfile.



Review How do I serve static assets when using Aptible? for in-depth advice on collecting and serving static files.

Automate Database Migrations

Finally, your app probably expects you to run database migrations upon deploy to ensure your app code and database are in sync.

You can tell Aptible to run your migrations by adding a .aptible.yml file in your repository.

The file should be named .aptible.yml, and found at the root of your repository (make sure to check it in after creating it).

Here is a sample .aptible.yml file to automate Database migrations:

  - python migrate

Configure Django

We're going to pass Configuration to Django via the Container Environment (i.e. environment variables), so you'll need to configure Django to use those.

There are two variable that matter:

  • DATABASE_URL: we'll use this to configure Django's database connection. It should be the connection URL for your PostgreSQL Database.
  • ALLOWED_HOSTS: we'll use this to set Django's ALLOWED_HOSTS setting. It should be a comma-separated list of allowed hosts.

To read the DATABASE_URL, the best option is to use the dj-database-url module.

First, add it to your requirements.txt:


Then use it in

import dj_database_url
DATABASES = {'default': dj_database_url.config()}

As for ALLOWED_HOSTS, you can add this to your

ALLOWED_HOSTS = [h.strip() for h in os.environ.get("ALLOWED_HOSTS", "").split(",")]

Finally, you should also ensure Django is logging to the console so you can read your logs via a Log Drain. Unless your app is already configured to log the console, add this to your

    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console': {
            'class': 'logging.StreamHandler',
    'loggers': {
        'django': {
            'handlers': ['console'],
            'level': os.getenv('DJANGO_LOG_LEVEL', 'INFO'),

Bring it all together

At this point, you're almost ready to deploy.

All that is left to do is put the pieces together by configuring your App to point it to your Database, then you'll be ready to push your code to Aptible.

To add the required environment variables, use the aptible config:set command as documented below. Make sure you set or substitute $APP_HANDLE and $DATABASE_URL with their proper values.

ALLOWED_HOSTS requires a little more attention than other variables. It must be set to the domain you intend to use with your app (or domains). For example, if your domain is, then you'd use for ALLOWED_HOSTS.

aptible config:set --app "$APP_HANDLE" \

Once you're done, push your code to Aptible by adding Aptible as a git remote for your app, and then using git push to push your code:

git remote add aptible "$GIT_REMOTE"
git push aptible master

Deploy logs will stream to your terminal. They'll be useful in case anything goes wrong to understand the cause of the failure.

Add an Endpoint

At this point, your App is running on Aptible. What's next is expose it on the Internet!

Follow the instructions here to proceed: How do I expose my web app on the Internet?.

For a Django app, you'll have to make sure the Custom Domain you use for your Endpoint matches the ALLOWED_HOSTS you set earlier (you can also update ALLOWED_HOSTS again via aptible config:set).