Upgrade Releases With Distillery

Written by Pete Corey on Jan 9, 2017.

Now that we’ve deployed our first Elixir application using Distillery, let’s dive into the process of building and deploying a “hot upgrade” for our application!

We’ll move through the process of making a change to our application, using Distillery to build our upgrade, and then deploying the upgrade with zero downtime.

Making Our Changes

With the goal of keeping things simple, let’s make a small change to our application’s index.html.eex file. We’ll add a new <h3> tag that shows we’ve upgraded our application:

<div class="jumbotron">
  <h2><%= gettext "Welcome to %{name}", name: "Phoenix!" %></h2>
  <h3>Version 0.0.2!</h3>

Next, we’ll need to upgrade our project’s version in our mix.exs file:

def project do
  [app: :hello_distillery,
   version: "0.0.2",

It’s important to upgrade our project’s version so distillery can correctly build an upgrade/downgrade patch for our application.

Problems With Our Build

And with that, we should be ready to build our upgrade release. The process for building an upgrade is very similar to that of building a normal release:

MIX_ENV=prod mix do compile, phoenix.digest, release --env=prod --upgrade

Unfortunately, due to how we configured our project in the last article, this upgrade build will fail:

==> Assembling release..
==> Building release hello_distillery:0.0.2 using environment prod
==> Failed to build release:
    Hot upgrades will fail when include_erts: false is set,
    you need to set include_erts to true or a path if you plan to use them!

Because we installed Erlang on our production machine, we set include_erts to false in our release configuration file, indicating that we didn’t want to include the Erlang runtime in our final build.

Distillery is complaining that when building upgrade releases, include_erts either needs to be true (which will include the Erlang runtime installed on our development machine in the release), or a path pointing to the Erlang runtime we want to include in the release.

A Tale of Two Erlangs

My development machine is a Macbook, and my production machine is an Amazon Linux EC2 instance. This means that including my development machine’s version of Erlang in the release is not an option.

This means that we’ll have to copy the instance of Erlang we installed on our production server onto our development server and point to it with include_erts.

The Distillery walkthrough touches in this in the “Deploying Your Release” section:

If you are deploying to a different OS or architecture than the build machine, you should either set include_erts: false or include_erts: "path/to/cross/compiled/erts".

The latter will require that you have built/installed Erlang on the target platform, and copied the contents of the Erlang lib directory somewhere on your build machine, then provided the path to that directory to include_erts.

Following this advice, we’ll copy the Erlang runtime from our production server into a folder on our development machine (~/al-erlang):

scp -i ~/hello_distillery.pem -r \
    ec2-user@ec2...amazonaws.com:/usr/local/lib/erlang \

Now we can change our include_erts to point to our newly downloaded ~/al-erlang directory:

set include_erts: "/Users/pcorey/al-erlang"

And finally, we can build our upgrade release:

MIX_ENV=prod mix do compile, phoenix.digest, release --env=prod --upgrade

Hot Deploying Our Upgrade

Now that we’ve successfully built our upgrade release, we can deploy it to our production server.

The first thing we’ll need to do is ssh into our production server and create a 0.0.2 folder in our application’s releases directory:

mkdir ~/releases/0.0.2/

Next, we’ll hop back over to our development server and copy our newly built release tarball into that new directory:

scp -i /hello_distillery.pem \
    _build/prod/rel/hello_distillery/releases/0.0.2/hello_distillery.tar.gz \
    ec2-user@ec2-...amazonaws.com:/home/ec2-user/releases/0.0.2/ \

Lastly, we’ll switch back to our production server and run the upgrade command, passing in the new version of our application that we just uploaded:

./bin/hello_distillery upgrade 0.0.2

If everything went well, we should be able to refresh our application in the browser and see our "Version 0.0.2!" message!

Final Thoughts

Minus a few burs and rough edges, Distillery is a fantastic tool for building and deploying Elixir/Phoenix applications.

I imagine that all of the sticking points I encountered can be smoothed out with a combination of well-designed build scripts and building releases on a machine with the same architecture as the production environment.

Looking to the future, it looks like edeliver does exactly that. Expect to see an article in the next few weeks about simplifying the deployment process with edeliver!

Deploying Elixir Applications with Distillery

Written by Pete Corey on Dec 26, 2016.

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 \

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:

Intentionally Learning Elixir

Written by Pete Corey on Dec 19, 2016.

I’ve been programing computers in one way or another since I was ten years old. This means that I’ve had to teach myself quite a bit over the years.

My usual method of learning new programming concepts is to immerse myself in blog posts, online tutorials, forums, and chat rooms, trying to absorb as much information as I can. Unfortunately, I’ve come to realize that this can be a slow, unfocused method of learning.

When learning from scattered resources, information can come to me in an unideal order and from authors with entirely different outlooks and perspectives on the topics they’re teaching about.

Wanting to fast-track learning Elixir, I decided to try something I’d always shied away from. Reading books!

I’ve spent the past two weeks reading Programming Elixir (affiliate link) by Dave Thomas.

I picked Programming Elixir over the other multitude of books on Elixir because it’s often touted as the best introductory book to the language. After reading it, I’d have to agree that’s it’s a fantastic entry point.

To get the most out of the experience, I decided to read through the book in an intentionally focused way, reproducing most examples on my own machine, and completely (nearly) every exercise.

At the end of the day, I can happily say that the time investment is paying off. While I originally thought I had a grasp on Elixir, I feel significantly more comfortable with all of the nuances of the language after having read the book.

Next, I plan on reading Elixir in Action (affiliate link) by Sasa Juric to get a better handle on OTP and “thinking in processes”.

This experience has shown me that books are an invaluable tool for learning programming concepts. The curated, focused approach of following a single author’s train of thought through a topic really does give the reader a solid understanding of the topic.

If you’re looking for a book on Elixir, I highly recommend starting with Programming Elixir (affiliate link).