Elixir Releases: Moving Past Elixir 1.8 and Distillery 2.0
Elixir 1.9 introduced built-in support for releases, a need that was previously served (and continues to be) by the Distillery package. An app being deployed with Distillery 2.0 on a pre-1.9 version of Elixir has two upgrade paths, so we’ll look at those options, discuss their pros and cons, and see what changes might be required to make the transition.
- Should We Still Use Distillery?
- Elixir Built-in Releases Configuration
- How to Use Distillery with Elixir 1.9
- How to Switch from Distillery to Elixir Releases
Can / Should We Still Use Distillery?
The first thing to understand is that Distillery is still an option. In fact, it supports some advanced configuration and tools that aren’t yet available with built-in releases. In particular, it offers some tools to help with hot upgrades and lets you add custom commands to your release executable.
If you rely on these features, or if you’re happy with Distillery and don’t want to switch, you can keep using it. See the instructions below for using Distillery with Elixir 1.9.
How Are Built-in Releases Different?
If you’re able to move to the built-in releases in Elixir 1.9, I think you’ll find that the new mechanism offers simpler solutions to two of the biggest sticking points with deploying releases, especially for Phoenix apps: configuration and database migrations.
Configuring releases themselves
Distillery uses a dedicated configuration file at
rel/config.exs to configure releases, whereas Elixir releases are configured directly in
mix.exs. If you’re happy with the default release settings, you don’t even have to add anything to
mix.exs to build releases!
Runtime configuration for the app
Distillery allows you to overlay a runtime configuration file with some tweaks to your
rel/config.exs. Because this method makes sense for so many apps, it’s supported natively in the new built-in releases: Just put your runtime configuration (with
System.get_env() calls to pull in environment variables) in
config/releases.exs and it’s automatically loaded and merged in when the release is started.
Database migrations (and other one-off jobs)
Distillery provides a mechanism for adding custom commands to your release executable, which is useful for things like migrations and administrative tasks. It works great, but it can feel like a lot of configuration and boilerplate. Again simplifying things, Elixir releases include an
eval command that lets you run any app code with a simple invocation. In addition to simpler configuration, this method doesn’t even necessarily require you to know which code you might want to run before you build your release.
Instructions: Using Distillery with Elixir 1.9
If you want to stick with Distillery but upgrade Elixir, you’ll need to upgrade Distillery to version 2.1, which makes some adjustments to avoid collisions between the two release systems. The changes also require some adjustments in the app:
- When building releases, you’ll need to use
mix.releaseinvokes the built-in release mechanism.
- Instances of
Mix.Releases....will need to be replaced with
That should be all you need to keep using your existing Distillery release configuration in Elixir 1.9 and beyond.
Instructions: Moving from Distillery to Elixir 1.9 Releases
If you’re not using any advanced configuration with Distillery and want to switch, there are several changes required to move to the new system. I think you’ll find that most of them are painless and lead you to a simpler setup, but YMMV, especially if you’re doing fancy or nonstandard stuff in your releases (see above).
In Distillery, you’d use the
start command to run the app in the background and
foreground to run it in the foreground. In 1.9 releases,
start runs the app in the foreground while
daemon runs it in the background.
start is available in both systems but means something very different! You can find the full list of commands here.
Migration Scripts & Tools
To run this kind of job, you can invoke code directly via
...bin/app_name eval "MyApp.MyModule.func()" instead of custom commands. Any files related to those custom commands can be removed.
If you have multiple releases defined in
rel/config.exs or use other custom configuration options, you’ll need to transfer those to
mix.exs. The full set of options is documented here.
If you’re using a file like
rel/config/runtime_config.exs, move it to
config/releases.exs and make sure it follows these rules.
mix release.init in Elixir 1.9 generates
vm.args.eex contains the following comment:
-mode/-name/-sname/-setcookie are configured via env vars,
do not set them here
If you want to adjust other vm settings, you can do that in
vm.args.eex, but the ones listed above, being often environment and host-specific, can be managed by simply setting the right environment variables. See the full list of release-specific environment variables for more info.
Remove extra files
Because Distillery’s configuration is slightly more powerful and verbose, there are some extra files that can be removed when moving to 1.9 releases. They include:
- Anything in
rel/commands(and the folders itself)
rel/plugins(assuming it’s empty)
- Your old custom
vm.argsfile, if you set one up
Bottom Line: 1.9 is a Big Step Forward for Elixir
Making the transition to Elixir 1.9 releases has been pretty painless for our apps so far. We’ve found the new system meets our needs and streamlines our configuration and deployment story. Congrats to everybody who made it happen!