Deploy Phoenix to Dokku

2022-02-26

I have been an on-again-off-again user of Dokku for hosting my personal projects and experiments. It's a reliable and consistent way to host applications, very much like your own personal Heroku. It can run easily on a $5/month Digital Ocean droplet without too much fuss, and doesn't turn your apps off if they're not getting heavy use!

A lot has changed in the Elixir and Phoenix world however since I was last working in it, most notably the new mix release feature for deployment. I ran into some issues leveraging these for deploying to Dokku and eventually combined the official docs on the process with some changes to suite my needs.

Setting up buildpacks

Since Dokku relies on the same buildpacks Heroku does we can thankfully leverage that existing ecosystem. If you're just using Phoenix with esbuild we need just one buildpack, otherwise an extra one or two may be needed. In our case we just need to create the below file in the root of our project to get it setup, name it .buildpacks.

https://github.com/HashNuke/heroku-buildpack-elixir.git

We'll then need to combine that file with a config file with a few options called elixir_buildpack.config. Be sure to specify your Erlang and Elixir versions as it currently cannot use other methods of specifying them (such as a .tool-versions file).

# Erlang version
erlang_version=24.2.1

# Elixir version
elixir_version=1.13.2

# Invoke assets.deploy defined in your mix.exs to deploy assets with esbuild and delete once complete
hook_post_compile="eval mix assets.deploy && rm -f _build/esbuild*"

Configuration for Dokku

The final file we need is a Procfile to tell Dokku how to run our release.

web: mix phx.server

And lastly, we need to update the runtime config to let Phoenix know it's being deploy as an OTP release. Ensure the below line is uncommented or add it in the config/runtime.exs file.

config :my_app, MyAppWeb.Endpoint, server: true

With all that setup we should be able to do the usual setup for Dokku (create app, create db, link db, setup environment variables) and do a push for the app to be deployed.