Heroku allows you to build an app, push the code to a git repository and have it automatically deployed to a server. The beauty of this solution is that if you follow certain simple conventions, you don’t have to invest any brainpower into the deployment at all.

Then comes Dokku, which is built on the same principles as Heroku and can serve as a drop-in replacement for it on your own server. It is possible because many layers of Heroku app infrastructure are open source: Heroku-16 (the base Ubuntu-derived OS image), buildpacks, Procfiles etc. The main thing that makes it attractive is that it is small, very well designed and can be trivially managed by anyone on a $5 DigitalOcean node. If you need to host your own pet projects or experiments, I seriously recommend you to give Dokku a try.

One day I decided to dig deeper into Dokku to see how exactly it achieves Heroku emulation. Turns out, there is this thing called herokuish, written in a mix of Go and Bash that is made to support Heroku build and run tasks in regular Docker containers. Its core idea is simple: you just mount or copy your app’s source code into the container, type a few commands, and it figures out how to download dependencies, build the app and run it.

If you are here for a recipe, just follow these steps (assuming you are currently in the directory with your app):

docker run --rm -t -i -e USER=herokuishuser -e PORT=5000 -v $(pwd):/app gliderlabs/herokuish /bin/bash

# in the container
/build
/start web

You may proceed with editing your app’s code and run /build and /start web periodically to check that it works.

Mounting your app to /app is important, because if you follow the herokuish README you’ll get something like:

setuidgid: fatal: unable to run gunicorn: file does not exist

I’m not sure why at the time of this writing the official README suggests to mount your code to /tmp/app, because Dokku is apparently using the /app directory. I’ve spent non-trivial amount of time while figuring that out, and I hope it’ll spare you that time if you read this.