How to Deploy a Containerized Python Dash App to Heroku

November 15, 2019

I love using Plotly to build interactive visualizations. The syntax is very similar across R and Python, and plots looks great.

One challenge I have found is sharing these dashboards in the wild. This blog posts walks you through how to build a Plotly Dash App in a docker container that you can deploy to Heroku.

You can see the app live here:

https://dash-heroku-cookie-cutter.herokuapp.com/

img

GitHub repo here:

https://github.com/SamEdwardes/dash-heroku-cookie-cutter

Why did I create this project?

  • There are many tutorials on how to use Dash, Flask, Heroku, and Containers. But, I could not find any that included all of these elements.
  • I have found it tricky to get Pandas working on some virtual environments and/or containers
  • I will use this as a basic starting point for future dash/heroku projects

Getting Started

Note: many ideas were taken from https://medium.com/@ksashok/ for this README.

Step 1: setting up files locally

Create a new directory in your computer and create the following file structure:

.
├── Dockerfile
├── README.md
├── app.py
├── data
│   └── gapminder.csv
└── requirements.txt

Step 2: app.py

Create your dash app. See app.py for complete details. A few important things to note:

port: int(os.environ.get("PORT", 5000))

You must use the above code for Heroku to find the correct port. If not, you may get:

Web process failed to bind $PORT within 60 seconds of launch

Thanks to Ashok’s blog post for this tip.

At the end of your app.py file you should have the following code:

if __name__ == "__main__":
app.run_server(debug=False,
host="0.0.0.0",
port=port)

The key part of the above code is to have port=port.

Step 3: Dockerfile and Requirements.txt

I chose to use a docker image (amancevice/pandas) that started with Pandas, and then add in the dash requirements though the Dockerfile.

Dockerfile

  • Calling CMD ["python", "app.py"] at the end of the file runs the app.

Requirements.txt

  • At this stage I have not yet tagged the libraries with specific versions. It seems to be working without the tags fow now.

Step 4: Building the docker image

In the terminal entering the following command:

Terminal window
docker image build -t dash-heroku:latest .

Next you can validate if the image is working by running the image:

docker container run -d -p 5000:5000 dash-heroku

To see if your app is running open http://localhost:5000/ (you can click on this link and it should take you to your app).

While developing my app I found it helpful to use VS code with the Docker extension. It lets you develop from within the container so you can update your code and test in the container with less fussing around on the command line.

Step 5: Deploying to Heroku

To deploy to Heroku you must have the Heroku CLI installed. Once it is installed you can do the following in the command line.

Log into Heroku:

heroku container:login

Create a new app on Heroku, where it says dash-heroku-cookie-cutter choose any name you like:

heroku create dash-heroku-cookie-cutter

Create the container in Heroku:

heroku container:push web --app dash-heroku-cookie-cutter

Then release the app:

heroku container:release web --app dash-heroku-cookie-cutter

You should now be able to visit your app and see it in action. You can visit mine here:

https://dash-heroku-cookie-cutter.herokuapp.com/

Using Containers vs. Virtual Environments

There are two ways I have deployed apps to Heroku:

Overall I would recommend using the container process. I found even with using virtual environments there were many times were the app would run locally, but then would not run when I push to Heroku. Additionally, as my virtual environment grew in size Heroku began rejecting it because it was over 500 MB. With containers I don’t believe this limit exists.