Elixir deployments with Distillery: Running ecto migrations

Distillery is a great way to deploy elixir applications. It's not really obvious though how and when to run ecto-migrations for an application when deploying them with distillery as after building the application with distillery you'll only deploy a self-contained package and you can't run mix-tasks from a release (i.e. you can't run mix ecto.migrate).

There's a great blog post from plataformatec on how to run migrations with Exrm but we need to change it up a little bit to make migrations work with distillery.

Distillery provides boot-hooks to execute scripts pre- or post-start of the application. We can hook into that to run ecto migrations every time our application boots up.

To do that we create a module that holds our release tasks (for now that's only migrate):

defmodule Release.Tasks do  
  def migrate do
    {:ok, _} = Application.ensure_all_started(:my_app)

    path = Application.app_dir(:my_app, "priv/repo/migrations")

    Ecto.Migrator.run(MyApp.Repo, path, :up, all: true)

and add a post-start-hook to our rel/config.exs:

environment :prod do  
  set include_erts: true
  set include_src: false

  set post_start_hook: "rel/hooks/post_start"

boot-hooks are just scripts that get executed:

set +e

while true; do  
  nodetool ping
  if [ $EXIT_CODE -eq 0 ]; then
    echo "Application is up!"

set -e

echo "Running migrations"  
bin/my-app rpc Elixir.Release.Tasks migrate  
echo "Migrations run successfully"

In our boot-hook we make sure the application is fully up and then run our migrate-function from the Release.Tasks-module.

With that it's easy to run migrations when deploying your elixir-applications via distillery.

Thanks for reading and as always just drop me a line on twitter (@LevelbossMike) if you have questions. I am also available for consulting work and would be happy to help you and your company with your ember.js, javascript, ruby and elixir-projects.

comments powered by Disqus