Releasing Our Code
Understand the Elixir code release.
Introduction
One way Erlang achieves nine-nines application availability is by having a rock-solid release management system. Elixir makes this system easy to use.
Before we get too far, let’s talk about terminology. A release is a bundle that contains a particular version of our application, its dependencies, its configuration, and any metadata it requires to get running and stay running. A deployment is a way of getting a release into an environment where it can be used.
A hot upgrade is a kind of deployment that allows the release of a currently running application to be changed while that application continues to run. The upgrade happens in place with no user-detectable disruption. In this section, we’ll talk about releases and hot upgrades. We won’t dig too deeply into deployment.
Distillery: the Elixir release manager
Distillery is an Elixir package that makes most release tasks easy. In particular, it can take the complexity that is the source of our project, along with its dependencies, and reduce it down to a single deployable file.
Imagine we were managing the deployment of hundreds of thousands of lines of code into running telephone switches while maintaining all the ongoing connections, providing a full audit trail, and maintaining contractual uptime guarantees. This is very complex. And this was the task the Erlang folks faced, so they created tools that help.
Distillery is a layer of abstraction on top of this complexity. Normally, it manages to hide it, but sometimes the lower levels leak out, and we get to see how it’s made.
This course isn’t going to get that deep. Instead, we just want to give you a feel for the process.
Before we start
In Elixir, we version both the application code and the data it operates on. The two are independent. We might go for a dozen code releases without changing any data structures.
The code version is stored in the project
dictionary in mix.exs
. But how do we version the data? Come to think of it, where do we even define the data?
In an OTP application, all state is maintained by servers, and each server’s state is independent. So, it makes sense to version the application data within each server module. Perhaps a server initially holds its state in a two-element tuple. That could be version 0. Later, it’s changed to hold state in a three-element tuple. That could be version 1.
We’ll see the significance of this later. For now, let’s just set the version of the state data in our server. We use the @vsn
(version) directive:
defmodule Sequence.Server do
use GenServer
@vsn "0"
Now, let’s generate a release.
Our first release
First, we have to add distillery
as a project dependency. We open the sequence project’s mix.exs
file and update the deps
function.
defp deps do
[
{:distillery, "~> 1.5", runtime: false},
]
end
The runtime: false
option tells mix
that Distillery is not to be started with the running application.
Note: Remember to install the following dependency:
mix do deps.get
.
Distillery makes sensible choices for the various configuration options, so for a basic application like this, we’re now ready to create our first release. To start off we create the release configuration:
$ mix release.init
If you’re following along at home, have a look at rel.config.exs
(it’s too large to show here). The defaults look good, so let’s build the actual release. We’ll tell it we want a production version of the release. If we don’t do that, the release it generates will be for development and won’t be a self-contained package.
$ mix release
==> Assembling release..
==> Building release sequence:0.1.0 using environment prod
==> Including ERTS 9.1 from /usr/local/Cellar/erlang/20.1/lib/erlang/erts-9.1
==> Packaging release..
==> Release successfully built!
We can run it in one of the following ways:
Interactive: _build/dev/rel/sequence/bin/sequence console
Foreground: _build/dev/rel/sequence/bin/sequence foreground
Daemon: _build/dev/rel/sequence/bin/sequence start
Distillery got the application name and version number from our mix.exs
file, and packaged our application into the _build/dev/rel/
directory:
Get hands-on with 1400+ tech skills courses.