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.
Configuration
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 distillery.release
becausemix.release
invokes the built-in release mechanism. - Instances of
Mix.Releases....
will need to be replaced withDistillery.Releases...
inrel/config.exs
and elsewhere.
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 elixir releases (see above).
Startup Command
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.
So start
is available in both systems but means something very different! Here’s the full list of commands.
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.
Release Config
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
. Here’s the full set of options.
Runtime Config
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.
VM Config
Running mix release.init
in Elixir 1.9 generates rel/vm.args.eex
, rel/env.sh.ex
, and env.bat.eex
. 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:
rel/config.exs
- Anything in
rel/commands
(and the folders itself) rel/plugins
(assuming it’s empty)- Your old custom
vm.args
file, 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!
We're building an AI-powered Product Operations Cloud, leveraging AI in almost every aspect of the software delivery lifecycle. Want to test drive it with us? Join the ProdOps party at ProdOps.ai.