Deploying Elixir releases

13 Jul 2016

I have seen great posts about Elixir release deployments lately and I would like to share my experience deploying Elixir releases to production. After testing different approaches (from git cloning code in the target machine to building Docker images), I decided to go with, in my opinion, a simpler approach.

Deployment is critical

Deployment is one of the most important things in a project. It needs to be easy, fast and painless to rollback when things go wrong. Although it’s critical part of a project, it is sometimes overlooked. It’s not hard to find teams that deploy to a production-like environment only when they will release the project to the public, after months of development and thousands of commits.

Delaying a project deployment until you need to expose your project to the world, brings many unnecessary risks, like:

All those risks can be mitigated if the deployment starts early, is automated and it’s performed by everyone throughout the development phase.

Goals

The goals when defining the deployment strategy of this project, was to offer a really simple and fast way of getting a new release shipped. The TODO list while researching and implementing it was:

Development

Development

Before we get into the deployment, I think it’s important to give you some context about the project development cycle, since it has a direct impact on how the deploy is done. The numbers on the image means:

  1. The developer pushes her/his local changes to Github;
  2. CircleCI pulls the changes and run the automated tests. If all tests pass, then an Elixir release is created, using Exrm;
  3. The release is pushed to a AWS S3 bucket.

Some facts about this cycle:

Infrastructure

Infrastructure

The infrastructure that powers this project is quite standard, but let’s take a look on it into more details:

The infrastructure has its creation and setup automated by Ansible. All the information about the load balancers, web servers, databases, caches, etc are stored and managed by Ansible.

For that reason, using Ansible also for deployments seemed to be a really good fit for our case.

Deploying

For a post about “deployment”, we have spent a considerable amount of time talking about different things, but not really getting into the main topic… deployment.

Deployment

As mentioned earlier, we used Ansible for setting all the machines used by this project. Deploying a new version of the project, means running an Ansible Playbook, that contains all the tasks to be applied to the target machines.

That’s the command that someone (developer, web, Slack bot) runs in order to deploy a new version:

$ ansible-playbook --ask-vault-pass --extra-vars "version=[COMMIT]" -i [ENV] deploy.yml
    

Let’s break this command down into smaller parts:

When this command runs, several tasks are applied to the machines present in the environment inventory. Using the image above, let’s see what happens in each stage:

Migrating from Ruby to Elixir

FREE e-mail course

By joining this free, 5-lesson course, you'll receive personalized & actionable lessons that cover:

  • Is Elixir the right choice?
  • Getting the team up to speed
  • How to start your first Elixir project
  • Delivering a successful project
  • Next steps