DEV Community

Cover image for Run Dash+Poetry+Gunicorn as your own Docker container on Heroku
Ole Kristian Losvik
Ole Kristian Losvik

Posted on

Run Dash+Poetry+Gunicorn as your own Docker container on Heroku

I am totally a noob, and this should be seen only as a working example, and never be used for something serious. Feel free to suggest some improvements and comments!

Dash

The open source Dash platform is my main reason for my desire to learn to program. I am starting with simple data analytics and visualization, and hoping to get into AI and more complex matters later.

Poetry

Python comes in different versions, and all my packages do as well. Poetry makes life easier for me when learning to program. It both handles dependencies for my project, as well as providing me with a virtual environment with all my packages present!

This is a example configuration in my pyproject.toml.

[tool.poetry]
name = "dashes"
version = "0.1.0"
description = "Data analytics"
license = "GPL3"

[tool.poetry.dependencies]
python = "^3.10"
dash = "^2.4.1"
pandas = "^1.4.2"
numpy = "^1.22.4"
pyjstat = "^2.2.1"
dash-bootstrap-components = "^1.1.0"
dash-labs = "^1.0.8"
gunicorn = "^20.1.0"
whitenoise = "^6.2.0"

[tool.poetry.dev-dependencies]
flake8 = "^4.0.1"
isort = "^5.10.1"
autopep8 = "^1.6.0"

[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
Enter fullscreen mode Exit fullscreen mode

Docker

What Docker does, is a bit above my imagination. Still: it makes it possible to run pretty much software with a few Google searches.

There seems to be a trend towards slim Docker images for your containers, so I tried a multi stage build. First we are exporting the dependencies to a requirements.txt, and then in a new container we install dependencis and run the Gunicorn web server.

This is my Dockerfile:

################
# Stage: Build #
################

FROM python:3.10-slim AS build

ENV POETRY_VERSION=1.1.13

WORKDIR /app

# Export poetry dependencies to file
RUN pip install "poetry==$POETRY_VERSION"
COPY poetry.lock pyproject.toml ./
RUN python -m venv /app/venv
RUN poetry export --without-hashes --format requirements.txt --output /app/requirements.txt

#####################
# Stage: Production #
#####################
FROM python:3.10-slim AS prod

ENV PYTHONPATH=/app

WORKDIR /app

# Copy requirements from build stage, and install them
COPY --from=build /app/requirements.txt . 
RUN pip install --upgrade pip
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

# Create a non-root user to run the web server
RUN adduser -u 5678 --disabled-password --gecos "" appuser && chown -R appuser /app
USER appuser

# Run server
EXPOSE ${PORT:-8000}
CMD gunicorn --bind 0.0.0.0:${PORT:-8000} index:server

Enter fullscreen mode Exit fullscreen mode

Heroku

Heroku is a super solid cloud platform suitable for running your enterprise apps. However, they do also provide a free tier. It takes some time to warm up for some request, howeve super cool to test your apps with.

You need to tell Heroku that you have your own image to run, just download their CLI first. Use the Heroku CLI, and make sure to set your run stack to container: heroku stack:set container.

Heroku also loves to decide which port the app should be available at, so make sure to get their PORT from environment variables. See above for how I managed to read the port when present, and default to port 8000 if not provided – ${PORT:-8000}.

Needed to add a file to my repo, heroku.yml, as well

build:
  docker:
    web: Dockerfile
run:
  web: gunicorn index:server --bind 0.0.0.0:$PORT
Enter fullscreen mode Exit fullscreen mode

And then: finally my little data analytics dashboard is running on Heroku! Again - feel free to suggest improvements in the comments section.

Top comments (0)