Felipe Juárez
4 min readJul 17, 2017
title
title

Every alchemist requires good tools, and one of the greatest tools in the alchemist’s disposal is the distillery. The purpose of the distillery is to take something and break it down to its component parts, reassembling it into something better, more powerful. That is exactly what this project does — it takes your Mix project and produces an Erlang/OTP release, a distilled form of your raw application’s components; a single package which can be deployed anywhere, independently of an Erlang/Elixir installation. No dependencies, no hassle.

Distillery

In this post, I am going to talk about distillery A tool which I’ve been using the last eight months for deploying an Elixir application. Also, we are going to show how to integrate it in a project. For that, we are going to use the phoenix framework

Please, make sure that you have installed elixir and phoenix

Ok, let the show begin.

The first thing that we are going to do is create a phoenix project without brunch and ecto (just for this example). To achieve that, we need to run mix phoenix.new todo --no-ecto --no-brunch

❯ mix phoenix.new todo --no-ecto --no-brunch
* creating todo/config/config.exs
* creating todo/config/dev.exs
* creating todo/config/prod.exs
* creating todo/config/prod.secret.exs
* creating todo/config/test.exs
* creating todo/lib/todo.ex
* creating todo/lib/todo/endpoint.ex
* creating todo/test/views/error_view_test.exs
* creating todo/test/support/conn_case.ex
* creating todo/test/support/channel_case.ex
* creating todo/test/test_helper.exs
* creating todo/web/channels/user_socket.ex
* creating todo/web/router.ex
* creating todo/web/views/error_view.ex
* creating todo/web/web.ex
* creating todo/mix.exs
* creating todo/README.md
* creating todo/web/gettext.ex
* creating todo/priv/gettext/errors.pot
* creating todo/priv/gettext/en/LC_MESSAGES/errors.po
* creating todo/web/views/error_helpers.ex
* creating todo/.gitignore
* creating todo/priv/static/css/app.css
* creating todo/priv/static/js/app.js
* creating todo/priv/static/robots.txt
* creating todo/priv/static/js/phoenix.js
* creating todo/priv/static/images/phoenix.png
* creating todo/priv/static/favicon.ico
* creating todo/test/controllers/page_controller_test.exs
* creating todo/test/views/layout_view_test.exs
* creating todo/test/views/page_view_test.exs
* creating todo/web/controllers/page_controller.ex
* creating todo/web/templates/layout/app.html.eex
* creating todo/web/templates/page/index.html.eex
* creating todo/web/views/layout_view.ex
* creating todo/web/views/page_view.ex

Fetch and install dependencies? [Yn] Y
* running mix deps.get

We are all set! Run your Phoenix application:

$ cd todo
$ mix phoenix.server

You can also run your app inside IEx (Interactive Elixir) as:

$ iex -S mix phoenix.server

Once is finished, we verify that everything is OK by running the server. And we need to see the default phoenix page.

Now it is time to add distillery to our project. We modify our mix.exs file and add it as a dependency.

After that, we update our dependencies and compile the whole project with mix do deps.get, compile. Next, we proceed to change our config/prod.exs

In this file, we configure the URL to read the PORT from the system environment and we instruct Phoenix to start the server for all endpoints.

Before we create a release package, we need to initialize distillery

❯ mix release.init
Compiling 11 files (.ex)
Generated todo app

An example config file has been placed in rel/config.exs, review it,
make edits as needed/desired, and then run `mix release` to build the release

This command create rel/config.exs file. In this file, we can find the configuration for building a release. We are going to keep the default configuration. But, if you want to know more about this you can go to distillery configuration. There you will find a list of config options for releases and environments.

And that’s all, once we are done with this changes we can run MIX_ENV=prod mix release --env=prod for creating a release.

❯ MIX_ENV=prod mix release --env=prod
==> Assembling release..
==> Building release todo:0.0.1 using environment prod
==> Including ERTS 8.3 from /usr/local/Cellar/erlang/19.3/lib/erlang/erts-8.3
==> Packaging release..
==> Release successfully built!
You can run it in one of the following ways:
Interactive: _build/prod/rel/todo/bin/todo console
Foreground: _build/prod/rel/todo/bin/todo foreground
Daemon: _build/prod/rel/todo/bin/todo start

For testing our release we are going to use the Interactive approach. Therefore we will execute as stated in command line but will we prefix it with the port PORT=4000

❯ PORT=4000 _build/prod/rel/todo/bin/todo console
Erlang/OTP 19 [erts-8.3] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]

12:56:03.825 [info] Running Todo.Endpoint with Cowboy using http://localhost:4000
12:56:03.826 [error] Could not find static manifest at "/Users/makingdevs/Documents/todo/_build/prod/rel/todo/lib/todo-0.0.1/priv/static/manifest.json". Run "mix phoenix.digest" after building your static files or remove the configuration from "config/prod.exs".
Interactive Elixir (1.4.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(todo@127.0.0.1)1>

Now we put our ip address into our browser followed by PORT and we are going to see the default page as in the begining.

As a bonus, if you enter in interactive mode. When you hit the URL you will see how the console output update everytime you hit that URL.

❯ PORT=4000 _build/prod/rel/todo/bin/todo console
Erlang/OTP 19 [erts-8.3] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]

12:58:48.667 [info] Running Todo.Endpoint with Cowboy using http://localhost:4000
12:58:48.667 [error] Could not find static manifest at "/Users/makingdevs/Documents/todo/_build/prod/rel/todo/lib/todo-0.0.1/priv/static/manifest.json". Run "mix phoenix.digest" after building your static files or remove the configuration from "config/prod.exs".
Interactive Elixir (1.4.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(todo@127.0.0.1)1> 12:58:54.917 request_id=27n3ui1iisialbh41grg9g1btt9d67n8 [info] GET /phoenix/live_reload/socket/websocket
12:58:54.917 request_id=27n3ui1iisialbh41grg9g1btt9d67n8 [info] Sent 404 in 173µs
12:59:34.541 request_id=nmcl910kb02brqb5qsicm5ljl1a9iccj [info] GET /
12:59:34.542 request_id=nmcl910kb02brqb5qsicm5ljl1a9iccj [info] Sent 200 in 238µs
12:59:56.322 request_id=se02ut1a3fl5i9114ueta0f6ab9f44ke [info] GET /phoenix/live_reload/socket/websocket
12:59:56.322 request_id=se02ut1a3fl5i9114ueta0f6ab9f44ke [info] Sent 404 in 165µs
13:00:04.711 request_id=6omlkpefoom2abafgnco8t4tcuqec0c1 [info] GET /
13:00:04.711 request_id=6omlkpefoom2abafgnco8t4tcuqec0c1 [info] Sent 200 in 226µs

In case you have troubles, here is the repository to download this example.

I hope you can find interesting and helpful. Later we will sse how to create an upgrade for this project.

Good luck and have fun!

Felipe Juárez

Software Developer at MakingDevs, a competitive gamer currently playing SC2 and Clash Royale. I love beer, anime, manga, music my kids and my wife