The world’s leading publication for data science, AI, and ML professionals.

Heroku + Docker in 10 Minutes

Deployment for Python applications made easy – and it's free

Photo by Diego Fernandez on Unsplash
Photo by Diego Fernandez on Unsplash

It’s easy to launch a web application on a local machine when all that is required is to be good at a programming language. However, it takes a lot of trial and error to deploy a web application, especially when more tools are involved, and you now have to worry about the deployment environment, scalability, and other concerns. If you’re looking to deploy a Python web application (i.e. Flask/Django), this article is for you! You can skip the first three sections if you already have some knowledge of Heroku and Docker.

Update: This article is part of a series. Check out other "in 10 Minutes" topics here!

Table of Contents


Why Heroku?

Heroku is a cloud platform as a service (PaaS) that allows applications to be hosted on the cloud. For people looking for a free hosting platform for Python applications, Heroku is one of the top 10 choices (although there are paid tiers as well).

For the free tier, Heroku offers integration with GitHub and the use of Heroku Containers for deployment, referred to as dyno. I would also mention some of the caveats of using the free tier that I find cumbersome.

  1. It is not possible to choose a custom domain, so applications will be hosted with <app-name>.herokuapp.com domain
  2. There is no SSL certificate, but a workaround is to manually type in https:// to get the same secure lock icon
  3. Free dynos will sleep after some period of inactivity, therefore relaunching the application will take some time (~ 1 minute) for the container to start up
  4. The repository will be compiled into a slug, and the performance will start degrading if the slug size exceeds 500 MB. This would severely limit the repository size. A workaround is to compile your application into a Docker image and bypass the slug size requirement

Update: Heroku has removed its free tier as of Nov 2022, an alternative would be to use Google Cloud or Fly. If you are using the paid version of Heroku, feel free to read on!

Google Cloud vs. Fly.io as Heroku Alternatives

Why Docker?

Docker helps deliver the web application in packages called containers. Using containers is a best practice for Deployment since each container has its software, libraries, and configuration files, and is easy to scale your web application up or down. However, in Heroku free tier, I don’t think there is an option to scale the web application up.

The last caveat in the previous section was also the reason why I chose to switch from using Heroku containers to Docker containers. I was expanding my web application and realized my repository has grown too big and my web application is increasingly slow. After the switch to Docker containers, my web application runs even faster than on my local computer!

I would recommend using Heroku with Docker to future-proof your web application so you don’t have to perform the switch as I did.

Docker Crash Course

The instructions on how to create a container are usually written in a Dockerfile, and the files to ignore from the compilation are found in .dockerignore. Below is a sample of what .dockerignore file looks like, but this file is optional if you want Docker to compile everything in the repository.

__pycache__
*.pyc
env/
db.sqlite3
docs/
*.log

For Dockerfile, there are some commands that are commonly used,

  • FROM is used once at the start of Dockerfile to indicate which base image to use, for our case we would want to use a base image that supports Python
  • ARG defines variables that users pass in at build-time. In the example below, port is an argument to be passed in when building a Docker image
  • USER sets username or user group when running Docker image
  • COPY copies files and directories to the container
  • WORKDIR sets the working directory of the container
  • ENV sets environment variable
  • RUN runs shell command, which calls /bin/sh -c on Linux
  • EXPOSE informs Docker that the container listens on the specified network ports at runtime, used for testing Docker applications locally
  • CMD is used once at the end of Dockerfile and contains the final command to run execute the container

Information on the full list of Docker commands can be found on the Docker documentation. Below is a sample of what the Dockerfile looks like,

FROM python:3.8-slim
ARG port

USER root
COPY . /<your-app>
WORKDIR /<your-app>

ENV PORT=$port

RUN apt-get update &amp;&amp; apt-get install -y --no-install-recommends apt-utils 
    &amp;&amp; apt-get -y install curl 
    &amp;&amp; apt-get install libgomp1

RUN chgrp -R 0 /<your-app> 
    &amp;&amp; chmod -R g=u /<your-app> 
    &amp;&amp; pip install pip --upgrade 
    &amp;&amp; pip install -r requirements.txt
EXPOSE $PORT

CMD gunicorn app:server --bind 0.0.0.0:$PORT --preload

It is best to test if the Dockerfile is able to compile locally before deployment, which requires building the Docker image and running it.

  • To build Docker image: The following command passes in the port argument and the image name is tmp_image, docker build --no-cache --build-arg port=8060 -t tmp_image .
  • To run Docker image: The following command maps port of Docker image to local port so the web application can be viewed locally, docker run --rm -p 8060:8060 tmp_image

Deploy Docker on Heroku

Assuming you already have your folder structure for your web application, you only require 3 additional files for deployment to Heroku. Two of these files are instructions for Docker as explained in the previous section, and the last file heroku.yml contains deployment instructions for Heroku. Below is the sample project folder structure,

your-app
|-- .dockerignore
|-- app.py
|-- Dockerfile
|-- heroku.yml
|-- requirements.txt

For heroku.yml file, you only need to indicate that deployment is using Docker and the file looks like this,

build:
  docker:
    web: Dockerfile

And it’s completed! All that’s left is to follow the on-screen instructions to link Heroku to your codebase, and your web application will be ready after the build!


Hope you have learnt how to deploy Python applications on Heroku using Docker. If you’re interested to view my web application which is deployed the same way, the link is below!

Tools to make life easier

Thank you for reading! If you liked this article, feel free to share it.


Related Links

Heroku Deployment Documentation: https://devcenter.heroku.com/categories/deploying-with-docker

Dockerfile Documentation: https://docs.docker.com/engine/reference/builder/

heroku.yml Documentation: https://devcenter.heroku.com/articles/build-docker-images-heroku-yml


Related Articles