Dan's Blog

Run a self-hosted PAAS with Dokku

dokkuweb developmentdevopsdjango

Photo by Ricky Kharawala

Photo by Ricky Kharawala on Unsplash

Hosting your web application has become a more complex beast over the years with complex orchestration platforms such as Kubernetes and the dense jungle of oddly-named services on offer from Amazon and other cloud hosting providers. These APIs and platforms have grown to handle the many needs of modern devops and web applications, from service meshes to horizontal scaling on demand, complex logging and monitoring requirements and CI/CD deployment pipelines. Long-gone are the days when it was sufficient to FTP a bunch of files to your hosting provider and call it a day.

While these APIs and platforms have grown to meet the real demands of large, enterprise-scale web applications and teams, they can be overkill for the small startup and sole developer looking for a small, simple solution to get their app in front of users. There are solutions that meet the needs of static sites (this blog for example is a static site generated by Eleventy and hosted on Netlify) but not so many it seems for dynamic applications running Rails, Django or PHP and connecting to one or more databases.

Traditionally Heroku has fulfilled this role, making it as easy as possible to deploy a Rails or Django application with a few configuration files. While it has had a free tier sufficient for small demo apps, Heroku has long had a reputation for being very expensive at scale. How expensive of course depends on budget - compared to the annual salary of a Kubernetes expert it might be very cheap indeed - but still perhaps a bit pricey for a small SAAS or side project. There is concern that since its sale to Salesforce, development on Heroku has stalled:

Heroku is like a fallen civilization of elves. Beautiful, immortal, beloved by all who encountered it - but still a dead end.

That's not to knock Heroku - it's still used successfully by many small-to-medium sized companies that don't want or need the cost and complexity of Kubernetes or the AWS or Google Cloud platforms - and it nails a lot of things right.

Dokku is a self-hosted alternative to Heroku. Under active development, you can even re-use much of the same configuration as your Heroku deployment, but with the flexibility and low-cost of running it yourself.

Perhaps the easiest way to get started with Dokku is to use Digital Ocean's pre-installed Dokku image. Once you have set up your SSH keys on your server you can set up a new app and start to provision services such as PostgreSQL:

  dokku apps:create my-app
dokku plugin:install https://github.com/dokku/dokku-postgres.git
dokku postgres:create myapp-db
dokku postgres:link myapp-db my-app

You can then set up your local environment to deploy to your Dokku application. First you'll need a Procfile to tell Dokku what to run, just like that used by Heroku, for example for a Django or Flask app running behind Gunicorn:

  web: gunicorn --workers=5 --max-requests=1000 --max-requests-jitter=50 myapp.wsgi

and a runtime.txt to tell Dokku which image you need to run your application e.g.:

  python-3.10.2

As with Heroku, you can then deploy any changes from your local environment with Git:

  git remote add dokku dokku@my-site.com:myapp
git push dokku main

You can see a full tutorial and example here. As with Heroku you'll need to architecture a 12-factor app, for example using environmental variables for configuration and logging to stdout, and you'll probably want to use third-party services such as Mailgun for things like email.

Dokku has a rich ecoystem of plugins that cover most web development needs, from databases such as PostgreSQL or MySQL to LetsEncrypt. If you want to use Celery or another queuing library for managing asynchronous tasks, you can just install Redis or RabbitMQ and add a worker process to your Procfile:

  web: gunicorn ...
worker: celery worker --app=myapp

Unlike Heroku where you have to pay for additional services like task queue workers, you can run as many additional services as you want, provided your host has sufficient memory and CPU.

If you are running a Python app and need to install NLTK modules, just as with Heroku you can provide an nltk.txt file and Dokku will automatically detect this file install the listed modules on deployment e.g. :

  stopwords
wordnet
omw-1.4

Dokku works best when you are happy running a single-server setup, i.e. your web app, database and other services are all running on a single Droplet or other host. When you want to run something more scalable - e.g. a load balancer, multiple web app instances, a separate database service and so forth - you'll probably want to migrate to Digital Ocean apps or Heroku (or bite the bullet and learn Kubernetes...). But you can get pretty far running your app on Dokku on a Digital Ocean droplet with sufficient CPUs and RAM, especially if you are running a small low-traffic SAAS.