ML.
← Posts

Creating a Django Project and Deploying to Google App Engine 1

A step-by-step guide to creating a Django project and deploying it to Google App Engine.

SeongHwa Lee··4 min read

img
  • Table of Contents

Goal

We will create a Django project and deploy it to Google App Engine.

Development environment

  • MacOS Mojave 10.14.6
  • Python 3.7.4
  • Django 3.0
  • Google Cloud Platform SDK

This document is written for readers who are comfortable with the Django framework, the command line, and MySQL.

Process

I started using Google Cloud Platform at work to deploy applications. It is often compared to Amazon Elastic Beanstalk, but since I got started with GAE (Google App Engine) before ever using Elastic Beanstalk, I found it quite comfortable once I got used to it. The ability to easily deploy scalable web apps is a major advantage.

Installing the Google Cloud Platform SDK

Detailed instructions are available in the official Google Cloud documentation. Download the SDK from the website, extract the archive, and run the install.sh script inside it.

img
./google-cloud-sdk/install.sh

Restart your shell to apply the changes. Depending on which shell you use, run either source ~/.zshrc or source ~/.bashrc.

gcloud auth login

You can now log in to the Google Cloud SDK. Running this command opens a browser window where you enter your login credentials.

Setting Up a Google Cloud Platform Project

This tutorial uses Google App Engine for fast setup and deployment.

Before creating an App Engine instance, you need to create a Project. In GCP, all applications are managed at the project level.

Create a project as shown below.

img

gcloud config set project mysite

Then set the project you just created as your currently active project.

Django App Initialize

The basic Django application setup follows the official Django tutorial.

django-admin startproject mysite

Use the startproject command to create the mysite project.

Creating and Connecting a Database

CREATE DATABASE mysite CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

Create the database using the utf8mb4 character set, which supports emoji input. I personally prefer MySQL, so I used it here. As of March 2020, Google Cloud SQL supports MySQL, PostgreSQL, and SQL Server.

img

Open mysite/settings.py and configure it as follows.

if os.getenv('GAE_INSTANCE'):
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            'NAME': os.getenv('DB_NAME'),
            'HOST': os.getenv('DB_HOST'),
            'USER': os.getenv('DB_USER'),
            'PASSWORD': os.getenv('DB_PASSWORD'),
            # For MySQL, set 'PORT': '3306' instead of the following. Any Cloud
            # SQL Proxy instances running locally must also be set to tcp:3306.
            'PORT': os.getenv('DB_PORT'),
        }
    }
else:
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            'OPTIONS': {
                'read_default_file': os.path.join(BASE_DIR, 'prod.cnf'),
            },
        }
    }

prod.cnf

host = 000.000.000.000
database = mysite
user = root
password =
port = 3306
default-character-set = utf8mb4

Create prod.cnf in the project root. This file stores the connection settings for your local database.

Configuring app.yaml

When configuring the database earlier, we injected settings using os.getenv(). Where does that data come from? If you have read through the GAE tutorial, you already know: it comes from the app.yaml file. Let's write the app.yaml file, which is where nearly all deployment-related configuration for GAE lives.

runtime: python37
instance_class: F4
entrypoint: gunicorn -b :$PORT main:app

beta_settings:
  cloud_sql_instances: mysite:asia-northeast2:mysite

handlers:
  # This configures Google App Engine to serve the files in the app's static
  # directory.
  - url: /static
    static_dir: mysite/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

env_variables:
  DB_PROD: 'TRUE'
  DB_HOST: '/cloudsql/mysite:asia-northeast2:mysite'
  DB_PORT: '3306'
  DB_NAME: 'mysite'
  DB_USER: 'root'
  DB_PASSWORD: 'password'

Configuration for Google App Engine

from mysite.wsgi import application

app = application

Looking at the entrypoint field in app.yaml, it is set to main:app. This means it will run the app object from main.py. The application in the wsgi.py that Django generates by default represents the project we just created.

Deploying

gcloud app deploy

Remarkably, this single command is all you need. It automatically reads the app.yaml configuration. If you want to deploy to multiple environments, you can append a filename like dev.yaml to deploy using that specific configuration instead.

References