Dokku makes it very easy to deploy and run simpler web apps. Recently, I had to deploy a slightly more complex web app with multiple non-web worker services talking to each other. It’s surprisingly simple to get make this work.

Services talking to each other

The web app itself is built using Django, so Dokku deploys it using the Python buildpack. Let’s call this service W for web worker.

There is also Postgres, Redis, a Celery beat and Celery worker processes. I consider these services to be part of a simple web app since they are straightforward to set up using Dokku.

In the more complex setup, I have to run two additional services, service A and B using Go.

So W -> A -> B where W is exposed to the Internet using Dokku with NGINX.

Polyglot web app

Luckily, Dokku supports multiple buildpacks. Dokku just needs some markers that say it’s a Python and Go project. Having initialized Dokku using Python, I can simply add Go:

$ dokku buildpacks:add facebook https://github.com/heroku/heroku-buildpack-go
$ dokku buildpacks:list facebook
-----> facebook buildpack urls
       https://github.com/heroku/heroku-buildpack-python
       https://github.com/heroku/heroku-buildpack-go
Connection to server closed.

The services A and B run different Go executables compiled from the same code base. Dokku knows how to build a project with go.mod file by compiling all the main.go binaries.

In order to override the binary names a file bin/go-post-compile can be added with following contents:

#!/bin/bash
set -e

go build -o bin/a servicea/main/main.go
go build -o bin/b serviceb/main/main.go

The Procfile looks something like this:

release: python manage.py migrate
web: gunicorn config.wsgi:application --workers=2
worker: celery -A config.celery_app worker --loglevel=info
beat: celery -A config.celery_app beat --loglevel=info
b: bin/a
a: bin/b

Great! This is how to deploy multiple Processes using different tech stacks with Dokku. Let’s make them talk to each other.

Service communication

It’s trivial with Dokku to have a web app responding to requests with many other side car processes communicating through Redis or Postgres.

My service A is talking to service B via a HTTP API. Service A needs SERVICE_B_URL.

Dokku creator Jose Diaz-Gonzalez suggests to attach a separate network . Let’s assume our app is called facebook.

$ dokku network:create my-network
$ dokku network:set facebook attach-post-deploy my-network

After a restart service A is able to talk to service B on host facebook.a because of the process name defined in Procfile. Service B listens on port 8090 so the full SERVICE_B_URL would be facebook.a:8090.

Update the configuration:

$ dokku config:set facebook SERVICE_B_URL=facebook.a:8090

A can now talk to B!