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)
end
end
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"
end
#...
boot-hooks are just scripts that get executed:
set +e
while true; do
nodetool ping
EXIT_CODE=$?
if [ $EXIT_CODE -eq 0 ]; then
echo "Application is up!"
break
fi
done
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.