Deploy your Dash application with Google Cloud Platform App Engine

Data Science Campus GitHub

This guide has been created to help users deploy a dash application using Google Cloud Platform (GCP) App Engine, using a locally-stored file. For more information, visit the GitHub repository.

Step 1: Creating your Dash Application

Visit our GitHub repository to view all the files.

Important files:

  • main.py is the Dash application
  • .gcloudignore is like .gitignore for GitHub, it tells GCP what not to upload (for example here, I don’t want to upload all the screenshots used in this guide)
  • app.yaml is used to run the Dash app on GCP using gunicorn, which is needed for GCP
  • requirements.txt comprises the packages needed to run the Dash app (important: gunicorn is required in this file at the bare minimum)

main.py

The main.py python script comprises the following, which are split into sections below. The full script can be found at the bottom of this post.

Python Functions

This section has three functions: add numbers, multiply numbers and build banner. The first two are self-explinatory, the last just creates an image banner based on a file in the assets folder.

Load Data

This section loads the csv file from the /data folder, creates a pandas dataframe and then applies the add and multiply number functions.

Text

This section just contains free text to append to the Dash app.

Dash

This contains the Dash setup values, including the /assets folder.

Project Dashboard

This is the core of the Dash application.

app.layout = html.Div(children=[
    html.H1(
        children=[
            build_banner(),
            html.P(
                id='instructions',
                children=dash_text),
            ]
    ),

    dcc.Graph(
        id='example-graph',
        figure={
            'data': [
                {'x': data_df.index.values.tolist(), 'y': data_df['add_num'], 'type': 'bar', 'name': 'Add Numbers'},
                {'x': data_df.index.values.tolist(), 'y': data_df['multiply_num'], 'type': 'bar', 'name': 'Multiply Numbers'},
            ],
            'layout': {
                'title': 'Dash Data Visualization'
            }
        }
    )
])

This simply creates the image banner, then adds the free text (which has an id whose style can be edited in the /assets/dsc.css file, then adds the graph based on the loaded and manipulated data from /data/datacsv.

main

if __name__ == '__main__':
    app.server(host='0.0.0.0', port=8080, debug=True)

It is important you make a note of the port number and host!

requirements.txt

Here, this is the requirements.txt file, which tells GCP which packages to install.

Click==7.0
dash==1.6.0
dash-core-components==1.5.0
dash-html-components==1.0.1
dash-renderer==1.2.0
Flask==1.1.1
Flask-Compress==1.4.0
future==0.18.2
itsdangerous==1.1.0
Jinja2==2.10.3
MarkupSafe==1.1.1
numpy==1.16.5
pandas==0.24.2
pytz==2019.3
retrying==1.3.3
six==1.13.0
Werkzeug==0.16.0
gunicorn==19.3.0

app.yaml

This is a really important file, and needs to replicate what is put in your main.py script.

runtime: python
env: flex
entrypoint: gunicorn -b 0.0.0.0:8080 main:server

runtime_config:
    python_version: 3

This file tells GCP how to create the application. The first line specifies we want to build using python, the entrypoint line must replicate what is at the end of main.py (the host and port numbers), as well as what you call the python script (here main.py = main). This is the most likely file to corrupt a build. The runtime_config tells GCP we want to build using Python 3 (the default is Python 2).

Step 2: Deploy your Application to Google Cloud Platform

This guide builds on other guides such as Jamie Phillips’. However, we were not able to successfully deploy a Dash app following Jamie’s, or others, examples without heavy tweaks. We also include additional python functions to load data in our example here (Goodbye, World).

The following steps are to deploy a Dash application to GCP. If your app doesn’t work locally, you should fix that first as it won’t work on GCP (even if you pray real hard). If it works locally, but it doesn’t deploy, the majority of the time it will be due to the app.yaml file.

Step 2.1: Make a Project on GCP

Using the CLI or the Console Interface online (which we use below), create a new project with a suitable project name (here we call it dash-example).

New Project in GCP

Step 2.2: Make Yourself the Owner of Project

Make sure the project you’ve just created is selected on the console, then click ‘ADD PEOPLE TO THIS PROJECT’.

Add People to Project in GCP

Then input your user name and set the role to Project > Owner.

Add Member Roles to Project in GCP

That’s it for now on the Google Cloud Platform Console.

Step 2.3: Deploy Using gcloud Command Line Tool

If you haven’t installed the gcloud command line tool do so now.

Next, check your project is active in gcloud using:

gcloud config get-value project

Which will print the following on screen:

Your active configuration is: [default]

my-project-id

To change the project to your desired project, type:

gcloud config set project project-id

Next, to deploy, type:

gcloud app deploy

Then select your desired region (we use europe-west2, which is the London region)

If you have setup your configuration correctly then it will deploy the Dash app (after a while), which will be available at:

https://project-id.appspot.com/

Our deployed dash app in GCP\

Step 3: Restrict Access to your Application

By default your application will be accessible to anyone in the world. To restrict the access you can use Firewall Rules.

Update: We have killed the link to our application due to running costs, see this post for a cheaper way to deploy your application using Google Cloud Platform, publically.

main.py script

import dash
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
import os


# -------------------------- PYTHON FUNCTIONS ---------------------------- #


def add_numbers(first_num,second_num):
    new_num = first_num + second_num
    return new_num

def multiply_numbers(first_num,second_num):
    new_num = first_num * second_num
    return new_num


def build_banner():
    return html.Div(
        id='banner',
        className='banner',
        children=[
            html.Img(src=app.get_asset_url('dsc-logo2.png')),
        ],
    )


# -------------------------- LOAD DATA ---------------------------- #


csv_files_path = os.path.join('data/data.csv')

data_df = pd.read_csv(csv_files_path)

add_num_list = []
multiply_num_list = []

for index, row in data_df.iterrows():
    add_num_list.append(add_numbers(row['first_num'], row['second_num']))
    multiply_num_list.append(multiply_numbers(row['first_num'], row['second_num']))

data_df['add_num'] = add_num_list
data_df['multiply_num'] = multiply_num_list


# -------------------------- TEXT ---------------------------- #


dash_text = '''

This is an example of a DSC dashboard.
'''


# -------------------------- DASH ---------------------------- #


external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']

app = dash.Dash(__name__, external_stylesheets=external_stylesheets, assets_folder='assets')
server = app.server

app.config.suppress_callback_exceptions = True


# -------------------------- PROJECT DASHBOARD ---------------------------- #


app.layout = html.Div(children=[
    html.H1(
        children=[
            build_banner(),
            html.P(
                id='instructions',
                children=dash_text),
            ]
    ),

    dcc.Graph(
        id='example-graph',
        figure={
            'data': [
                {'x': data_df.index.values.tolist(), 'y': data_df['add_num'], 'type': 'bar', 'name': 'Add Numbers'},
                {'x': data_df.index.values.tolist(), 'y': data_df['multiply_num'], 'type': 'bar', 'name': 'Multiply Numbers'},
            ],
            'layout': {
                'title': 'Dash Data Visualization'
            }
        }
    )
])



# -------------------------- MAIN ---------------------------- #


if __name__ == '__main__':
    app.run_server(host='0.0.0.0', port=8080, debug=True, use_reloader=False)


Michael Hodge

By

Senior Data Scientist at ONS Data Science Campus.

Updated