Glenn Jones

Hello 👋 Welcome to my corner of the internet. I write here about the different challenges I encounter, and the projects I work on. Find out more about me.

Deploy an Elixir Phoenix application to the smallest DigitalOcean droplet using Dokku

I am using Dokku 0.6.5, Elixir 1.3.3 and Phoenix 1.2.0. Do mix phoenix.new -v to see the version of Phoenix you’re using. I highly recommend using kiex to manage your Elixir versions.

I am assuming for this walkthrough that:

  1. You have an elixir / phoenix app ready to be deployed. If not, go ahead and grab any example phoenix project.
  2. You know how to work with ssh-keys. If not, see this digitalocean article.
  3. You have a digitalocean account. If you don’t: please register through my digitalocean referral link to get 10$ in credit.

During this walkthrough you will among others learn how to:

So, lets get started!

A. Phoenix app configuration

Configuring your app consists of three parts: tweaking the project settings, setting the right buildpacks and creating a Procfile.

For tweaking the settings of your project, have a look at ashleyconnor.co, paragraph 2. Those are all the relevant settings that need to be adjusted.

Then, create a .buildpacks file in the root of your project and enter:

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

Buildpacks allow you to sit back while your app gets deployed. As you can see, they are basically mimicked by dokku from heroku. They are great. If you want to enforce a certain Elixir version, you can do that by adding settings for the buildpack. If you insist on using Elixir 1.3.3 for example, add a elixir_buildpack.config file to the root of your folder and add

elixir_version=1.3.3

For more information about those settings, visit their repo.

Then create a Procfile in the root of your project. The procfile is executed to activate your app, once it’s ready. We will later set the environment variable MIX_ENV=prod, so for now the Procfile can simply contain:

web: mix phoenix.server

B. Configure your droplet

Credit where due: this part of the walkthrough effectively comes from rubyfleebie. Go have a look at his blog if you’re also busy with Ruby

Go ahead and create a new droplet. Use ‘One-click apps’ and select Dokku 0.6.5 on 14.04. Select the 5$/month size, select a region, add your SSH key, think of a nice name for your droplet and click create. Mine will be called “magicaltestapp”.

Once your droplet is done setting up, test if you can ssh into it. Use ssh root@the_ip_of_the_droplet. If it doesn’t work, go back and fix your ssh keys.

So, when ssh’d into your droplet, first do: bash cat /root/.ssh/authorized_keys | sshcommand acl-add dokku dokku Whatever the outcome of that command, this will ensure you can deploy with dokku.

Secondly, we’re going to make a swapfile that will ensure you have more space available when compiling dependencies. This way, we prevent the

(Mix) Could not compile dependency idna, /root/.mix/rebar command failed. If you want to recompile this dependency, please run: mix deps.compile idna

error that one can solve with a bigger droplet OR a swapfile (see this issue).

Again: this comes from rubyfleebie, I am paraphrasing here for your convenience

Read the RubyFleebie blogpost if you care what exactly the following commands do. Otherwise, simply execute the following commands, one-for-one.

sudo fallocate -l 2048m /mnt/swap_file.swap
sudo chmod 600 /mnt/swap_file.swap
sudo mkswap /mnt/swap_file.swap
sudo swapon /mnt/swap_file.swap

Then open /etc/fstab with your favorite editor (I use vim, so sudo vim /etc/fstab). And add the following entry below the existing entry: /mnt/swap_file.swap none swap sw 0 0. Then your swap file should be set up.

C. Create dokku app

Ssh into your server and execute: dokku apps:create magical_test_app. It’s possible to have multiple apps running on your droplet, just realise that you can only expose one to an actual domainname (as far as I’ve been able to figure out, please let me know if you know how to bypass this). The others will all be your-domainname.com:port-nr.

D. Create database on postgres

Do sudo dokku plugin:install https://github.com/dokku/dokku-postgres.git. Wait for the plugin to be installed and then do dokku:postgres create magical_test_app_db. This will create a database. Then link that database to your dokku app by running dokku:postgres link magical_test_app_db magical_test_app. That will expose a DATABASE_URL and enable your application to use the db.

E. Set remote & push

Your remote will be in the format of: dokku@the_ip_of_your_app:your_app_name. For me I set my remote with: git remote add dokku-production dokku@111.111.111.11:magical_test_app. Then push to the remote.

This will trigger a first deployment that should not fail.

F. Config / tweak dokku app

Phoenix apps need two more variables to be available: HOSTNAME and MIX_ENV. My app initially runs without them but it’s best to add them nonetheless.

You can set those environment variables by ssh’ing into your droplet and executing dokku config:set your_app_name HOSTNAME=some_value.

HOSTNAME is usually your domainname. If you are not linking this droplet to a domainname, use the ip of your droplet plus the portnumber. You can see the portnumber at the very end of the console output when you deployed. Otherwise, run dokku proxy:ports name_of_your_app to see it. It’s the host port that you’re after.

So for example, I run:

dokku config:set magical_test_app HOSTNAME=111.111.111.11:48813
dokku config:set magical_test_app MIX_ENV=prod

G. Running tasks in the dokku app environment

An often forgotten last job is to run your migrations. Ssh into your droplet and run dokku run name_of_your_app some_task. To migrate, for example, do dokku run magical_test_app mix ecto.migrate. If you want to interact directly within your project, run dokku run magical_test_app iex -S mix.

After doing this, your app should be ready to go. Visit your domainname or ip:hostname to visit the app. For me that would be http://111.111.111.11:48813.

Enjoy!

Links

Previous: Elixir ecto - how to group and count records by week
Next: Adding persistent storage to dokku