Hosting Django on Google App Engine

Prerequisite

Before you start, make sure:

1. Setup a Google Cloud Project with an SQL database

  1. Create an SQL instance. The db-f1-micro tier is the smallest tier and costs about €10 a month.
gcloud sql instances create <DB-NAME> \ 
    --database-version=POSTGRES_11 \
    --tier=db-f1-micro \
    --region=europe-west3 \
    --root-password=<PICK-A-ROOT-PASSWORD>

For more options, see other available tiers and other available regions.

  1. Retrive your database information. We’re more specifically interested in connectionName:
gcloud sql instances describe <DB-NAME> | grep connectionName
  1. (Optional) Create a dedicated user
gcloud sql users create admin --instance <DB-NAME> --password=<PICK-A-PASSWORD>
gcloud sql users list --instance <DB-NAME>

2. Prepare your Django settings for production

  1. Ensure you have a requirements.txt listing your dependencies. If not, you can generate one:
pip freeze > requirements.txt
  1. Create a file <ROOT_FOLDER>/<PROJECT_NAME>/settings-production.py, right next to your current settings.py file.
<ROOT_FOLDER>
    └── <PROJECT_NAME>
        ├── __init__.py
        ├── wsgi.py 
        ├── urls.py 
        ├── settings.py 
        └── settings-production.py 

This file is going to host our production settings.

# file: settings-production.py  

from .settings import *

DEBUG = False
ALLOWED_HOSTS = '*'
STATIC_ROOT = BASE_DIR / 'static'

if os.getenv('GAE_APPLICATION', None):
    # Running production mode on App Engine, connect to Google Cloud SQL using
    # the unix socket at /cloudsql/<your-cloudsql-connection string>
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.postgresql_psycopg2',
            'HOST': '/cloudsql/<CONNECTION_NAME>',
            'USER': '<YOUR-USERNAME>',
            'PASSWORD': '<YOUR-PASSWORD>',
            'NAME': '<YOUR-DATABASE>',
        }
    }
else:
   # Runnin production mode on localhost, connect to Google Cloud SQL using 
   # Cloud SQL Proxy: https://cloud.google.com/sql/docs/postgres/sql-proxy
   DATABASES = {
       'default': {
           'ENGINE': 'django.db.backends.postgresql_psycopg2',
           'HOST': '127.0.0.1',
           'PORT': 3307,
           'USER': '<YOUR-USERNAME>',
           'PASSWORD': '<YOUR-PASSWORD>',
           'NAME': '<YOUR-DATABASE>',
       }
   }

3. Prepare for Google App Engine

  1. In your root folder, create a main.py file with the following content. By default, Google App Engine will look for a wsgi application exported main.py.

    It is usual for a django instance to have migrations python manage.py migrate to run or static files to collect python manage.py c ollectstatic. We’ll also use this file to perform any step that need to be run before starting the server.

    # file: main.py
    
    from web.wsgi import application
    from django.core import management
    
    # replaces `python manage.py migrate` 
    management.call_command("migrate")
    
    # replaces `python manage.py collectstatic` 
    management.call_command("collectstatic", '--noinput')
    
    app = application
  2. In your root folder, create a app.yaml file with the following content.

    runtime: python38
    
    handlers:
    # This configures Google App Engine to serve the files in the app's static
    # directory.
    - url: /static
     static_dir: static/
    
    # This handler routes all requests not caught above to your main app. It is
    # required when static routes are defined, but can be omitted (along with
    # the entire handlers section) when there are no static files defined.
    - url: /.*
     script: auto
     secure: always
     redirect_http_response_code: 301
    
    env_variables:
     DJANGO_SETTINGS_MODULE: <PROJECT_NAME>.settings-production

4. Deploy 🚀

Now is the easiest part:

gcloud app deploy

Troubleshooting

  • Viewing your logs

    gcloud app logs tail
  • Viewing your source files

    gcloud app open-console

I hope this was helpful.