While churning through the exercises in Programming Elixir (affiliate link), I came across a section dedicated to deploying Elixir applications using the Elixir Release Manager (exrm
).
Browsing through the Elixir Release Manager project, I noticed that it is being replaced by Distillery:
I would highly recommend using [Distillery] moving forward, as most of my efforts will be put towards that project from now on.
Rather than learning how to use a deprecated tool, I decided it might be a better investment of my time to learn how to deploy Elixir applications using Distillery.
Below is a guide for doing a basic release with Distillery. For the most part, the instructions are very similar to doing a release with exrm
, with a few minor differences.
Creating Our Application
Before we start, we’ll need an Elixir project we want to deploy. To keep things simple, we’ll use a bare-bones Phoenix application. We can create our application (called HelloDistillery
) with the phoenix.new
Mix task:
mix phoenix.new --no-ecto hello_distillery
Once we’ve got our application set up and tested locally (mix phoenix.server
), we can start the Distillery deployment process.
Installing Distillery
The first step of deploying an Elixir project with Distillery is to add Distillery as a dependency. In our mix.exs
file, add a dependency on :distillery
version 1.0
:
{:distillery, "~> 1.0"}
Now tell Mix to pull down the new dependency:
mix deps.get
Once installed, Distillery creates a new release
Mix task. If we try to run it, we’ll be told that we need to do some initial configuration:
mix release
==> You are missing a release config file. Run the release.init task first
Following that advice, we can generate our initial config file with the release.init
Mix task:
mix release.init
Review the newly generated rel/config.exs
file. For our purposes, the defaults should be fine.
Configuring Our Release
The last step before we build our first release is to do some final configuration on the environment we’ll be deploying.
In our case, we’ll be deploying the prod
environment. If we look in our config/prod.exs
file, we’ll see a comment block addressing releases:
# ## Using releases
#
# If you are doing OTP releases, you need to instruct Phoenix
# to start the server for all endpoints:
#
# config :phoenix, :serve_endpoints, true
#
# Alternatively, you can configure exactly which server to
# start per endpoint:
#
# config :hello_distillery, HelloDistillery.Endpoint, server: true
Following this advice and the advice in the Distillery Phoenix Walkthrough, we’ll add a few configuration options to our HelloDistillery
endpoint, and update its url
:
config :hello_distillery, HelloDistillery.Endpoint,
...
url: [ ... ],
server: true,
root: ".",
version: Mix.Project.config[:version]
Once we’ve made those configuration changes, we’re ready to build and deploy our release!
Building Our Release
Building our release with Distillery is an easy process.
If we’re deploying a Phoenix application, we’ll need to be sure that we’ve bundled our front-end assets. We can do that with the following command:
brunch build --production
Next, we’ll run a series of Mix tasks. First, we’ll compile our project. Next, we’ll compress and digest all of our static files. Finally, we’ll build our prod
release:
MIX_ENV=prod mix do compile, phoenix.digest, release --env=prod
The mix release
task builds our release and places it in the _build
folder. To make sure everything went well, we can run the release locally using the following command:
PORT=8080 ./_build/prod/rel/hello_distillery/bin/hello_distillery foreground
If the release was successful, we should see our application’s server logs in the console, and we should be able to access your application at http://localhost:8080
.
Deploying Our Release
At this point, I’ll assume that you’ve already provisioned the machine you’ll be using for your production environment.
As a side note, I decided to deploy my application to an Amazon EC2 instance running 64 bit Amazon Linux.
Because we’re using the default configuration value of include_erts: false
, we’ll need to be sure that Erlang is installed on the machine we’ll be deploying our release to.
Following these instructions, I was able to easily build Erlang from source and install it on my production machine. You may also have luck with a pre-compiled Erlang package.
Be sure to use the same version of Erlang on your production machine as the machine you built your release on. If you do not, you may encounter obtuse errors when trying to run your release.
Once our machine is provisioned and Erlang is installed, we’ll copy our release tarball from our development machine up to our production machine:
scp -i ~/hello_distillery.pem \
_build/prod/rel/hello_distillery/releases/0.0.1/hello_distillery.tar.gz \
ec2-user@ec2-...amazonaws.com:/home/ec2-user
Be sure to tweak this command to suite your needs. I’m authenticating with a pem
file stored in my home directory, and deploying to the home directory of the default ec2-user
of my Amazon EC2 instance.
Once our release tarball is pushed up to our production server, we’ll need to extract it and run the release.
On the production server, extract the newly uploaded tarball:
tar -xzf ~/hello_distillery.tar.gz
Now is the moment of truth. Run the release binary using the foreground
option:
PORT=8080 ./bin/hello_distillery foreground
If everything went well, we should see our application’s server logs in the console. Additionally, we should be able to access our application at our production machine’s host on port 8080
(granted you’ve properly opened that port).
Now that we know everything works, kill the server process. This time we’ll run the hello_distillery
application as a daemon:
PORT=8080 ./bin/hello_distillery start
Once we’ve started the application, we can ensure that it’s running with a ping:
./bin/hello_distillery ping
> pong
And with that, we’ve deployed a basic Phoenix application using Distillery!
Final Thoughts
This was a simple run-through of a happy-path first deployment using Distillery.
I highly recommend you check out Distillery’s documentation, especially the Walkthrough and Phoenix Walkthrough sections. They go into much more detail about the various aspects of deploying with Distillery.
Overall, the process of deploying an application with Distillery was very similar to the Elixir Release Manager process described in Programming Elixir.
If you’d like to see Distillery in action, check out this short webm of entire entire deployment process: