[Перевод] Elixir: Развёртывание приложений с помощью Edeliver

5f84608add734cc78ce91a774f8ac6fb.png

Мы уже обсуждали сборку и развёртывание приложений Elixir(перев: с помощью exrm): как осуществлять миграции поверх релиза или как работать с переменными среды. Пришло время открыть для себя ещё один инструмент, который поможет развёртывать Elixir приложения.


Практика развёртывания Elixir приложений и дальнейшее отслеживание их работы на нодах с помощью Exrm позволяет нам чувствовать себя гораздо увереннее в вопросах управления релизами в production. Однако возникает следующий вопрос: как управлять самим процессом развёртывания? Конечно, мы можем воспользоваться Capistrano, особенно если в мир Elixir мы пришли из Rails. Но посмотрим на цитату из Edeliver README:


edeliver основан на доставке и предоставляет bash-скрипт для сборки и развёртывания Elixir и Erlang приложений, а так же позволяет совершать «горячее» обновление кода.

Пытаться организовать весь процесс развёртывания вручную — это жёсткая головная боль с кучей повторяющегося кода. А вот использование Edeliver для развёртывания оказалось очень простым с первой же попытки! В конце концов, весь процесс развёртывания уместился в один меленький bash-скрипт:


#!/bin/bash -ex

BRANCH=${1:-master};

mix edeliver build release --branch=BRANCH --verbose
mix edeliver deploy release to production --verbose
mix edeliver start production --verbose
mix edeliver migrate production up --verbose

Скорее всего Вам придётся подкрутить этот скрипт под собственные нужды. Мы используем его только для развёртывания в production, но Вы так же можете использовать его и для staging развёртываний. Описание того, как всё это работает — под катом.


Как это работает


Как мы видели в README, Edeliver работает в основном с помощью bash-скриптов. Команды Mix исполняются с помощью Elixir, но фактически они запускают bash-скрипты. Некоторые инструкции терминала выполняются локально: они создают новые инструкции, которые будут выполнятся на удалённых серверах с через RPC.
Давайте углубимся в некоторые аспекты работы библиотеки.


Окружение


Edeliver представляет собой отличную возможность запускать и доставлять релизы в различные окружения. Концепция окружений проста: build, stage и production. Тут всё понятно, разве что некоторые нюансы есть у окружения build.


Для того, чтобы релиз благополучно запускался на рабочем сервере, он должен быть собран на машине с такой же архитектурой. Всё дело в том, что Edeliver использует Exrm для сборки релизов. Exrm будет использовать свои NIFы (это функции, написанные на C для Erlang), которые могут различаться в зависимости от архитектуры машины, поэтому, к примеру, релиз собранный на OSX может не работать на Linux. Вы можете почитать подробнее об этом вот в это пичальке Phoenix, где люди обсуждают проблемы кросс-компиляции и всякие другие выкидоны Exrm.


Короче говоря, чтобы использовать build окружение на нашей машине разработчика, у неё должна быть такая же архитектура как и на staging и production машинах. Иначе работать не будет.


Для конфигурации наших окружений, нужно создать папку .deliver в нашем проекте и добавить конфигурационный файл. Посмотрим, что авторы Edeliver советуют нам в него записать:


#!/usr/bin/env bash

APP="your-erlang-app" # name of your release

BUILD_HOST="build-system.acme.org" # host where to build the release
BUILD_USER="build" # local user at build host
BUILD_AT="/tmp/erlang/my-app/builds" # build directory on build host

STAGING_HOSTS="test1.acme.org test2.acme.org" # staging / test hosts separated by space
STAGING_USER="test" # local user at staging hosts
TEST_AT="/test/my-erlang-app" # deploy directory on staging hosts. default is DELIVER_TO

PRODUCTION_HOSTS="deploy1.acme.org deploy2.acme.org" # deploy / production hosts separated by space
PRODUCTION_USER="production" # local user at deploy hosts
DELIVER_TO="/opt/my-erlang-app" # deploy directory on production hosts

В общем всё просто и прозрачно, надо только удостовериться в наличии ssh доступа ко всем перечисленным сервакам. Дополнительной фичей является то, что как уже горилось ранее, вполне реально запулить релизы на несколько серверов.


Как мне добавить дополнительные задания для моих процессов развёртывания?


Edeliver делает по стандарту только общие штуки для всех Elixir или Erlang приложений. Но если, к примеру, мы используем Phoenix, нам нужно запустить ещё парочку команд до того, как мы сгенерируем релиз. Самые важные — это


$ branch build --production

и


$ mix phoenix.digest

чтобы статика работала в наших релизах.


Для этого определим хук в нашем .deliver/config файле:


pre_erlang_clean_compile() {
  status "Preparing assets with: brunch build and phoenix.digest"
  __sync_remote "
    # runs the commands on the build host
    [ -f ~/.profile ] && source ~/.profile # load profile (optional)

    # fail if any command fails (recommended)
    set -e

    # enter the build directory on the build host (required)
    cd '$BUILD_AT'

    mkdir -p priv/static # required by the phoenix.digest task

    # installing npm dependencies
    npm install

    # building brunch
    brunch build --production

    # run your custom task
    APP='$APP' MIX_ENV='$TARGET_MIX_ENV' $MIX_CMD phoenix.digest $SILENCE
  "
} 

Код вверху был нагло выдран из документации к Edeliver, которая объясняет как работать с хуками, и почему-то сразу заработал.


Что там насчёт моих переменных окружения?


Мы уже рассказывали как правильно себя вести с переменными окружения так, чтобы не экспортировать их в build окружение вот тут, и это всё ещё работает! Впрочем, ещё кое-что надо иметь в виду.


Чтобы можно было менять окружения, необходимо добавить RELX_REPLACE_OS_VARS=true перед нашей командой запуска. Но это невозможно в Edeliver, потому что первая команда выполняется локально:


$ mix edeliver start production

Поэтому возможное решение — экспортировать RELX_REPLACE_OS_VARS в ваше production окружение.


Перед стартом


Похоже, что Edeliver — классная штука для управления релизами и вообще процессом развёртывания. Мне она показалась очень простой в использовании. В этой статье я никак не вникал во внутренности её работы, так что прочитайте README и всякие доки — там очень хорошо всё расписано.


Я деплою так, а ты как? Пиши в комментариях!

Комментарии (2)

  • 9 августа 2016 в 17:13

    0

    Вечная головная боль в elixir/phoenix — управление конфигами. Дело в том, что при компиляции конфиг приложения превращается в статический файл с намертво прибитыми гвоздями значениями. Т е любое изменение требует пересборки, причем с предварительно подсунутыми правильными данными. Зачем такое извращение было добавлено в язык — понятия не имею.
    Если кто-то знает как это можно адекватно обрабатывать — очень хочу услышать.

    • 9 августа 2016 в 17:16

      0

      Что насчёт System.get_env в конфиге?

© Habrahabr.ru