Деплой Elixir при помощи Docker
Для разработки приложений обычно используются различные технологии, такие как Ruby/Rails, Elixir/Phoenix, Java, Python или даже PHP. И как бы нам ни хотелось, использовать единый инструмент для деплоя всего, это невозможно.
Однако благодаря Docker-контейнерам разработчикам доступен унифицированный механизм деплоя приложений независимо от того, с помощью каких технологий они были созданы.
Как работать с Docker
Во-первых, будет достаточно всего одного Dockerfile
для того, чтобы создать рабочий образ и передать его напрямую в продакшн. Тем не менее создать рабочий образ не так просто. При использовании стандартного подхода в результате получаются тяжёлые образы, имеющие на этапе компиляции зависимости, которые совершенно не нужны во время выполнения программы.
Поэтому гораздо выгоднее разделить этот процесс на две части, то есть отделить разработку приложения (компиляцию, подготовку релиза) от деплоя и эксплуатации.
Далее рассматривается такой процесс для Elixir, хотя и для остальных языков применяются те же самые принципы. Например, запущенный контейнер с приложением на JavaScript содержит только откомпилированный код без каких-либо npm зависимостей.
Упаковка Phoenix-приложения в образ Docker
Как было сказано прежде, построение Docker-образа осуществляется в два этапа:
-
Разработка
-
Установить Erlang
-
Установить Elixir
-
Запустить
mix deps.get
-
Запустить
mix release
-
Сохранить дистрибутив
myapp.tar.gz
-
-
Подготовка релиза
-
Установить Erlang
-
Извлечь файлы из дистрибутива
myapp.tar.gz
в контейнер -
Готово!
-
Так как этот процесс одинаков для всех Elixir-приложений, был разработан простой модуль mix_docker, который выполняет все вышеперечисленные действия при помощи парочки mix-команд.
Немного о mix_docker
Утилита mix_docker предоставляет несколько mix-команд для простой и удобной упаковки Elixir-приложений в Docker-образы. Он построен на базе пакета distillery от
Ниже перечислены шесть этапов создания Docker-образа.
1. Добавить mix_docker в mix.exs
:
2. Дать образу имя в config/config.exs
:
3. Инициализировать настройки приложения:
После этого запустится distillery init
и создастся файл rel/config.exs
, и вам даже не придётся ничего менять – стандартные значения для Docker доступны из коробки.
4. Подготовить релиз
Создастся образ teamon/demo:build
, содержащий в себе пакет demo.tar.gz
.
5. Создание минимального образа приложения:
Архив demo.tar.gz
распакуется в минимальный Docker-образ, готовый к запуску в продакшн. Такие образы, как правило, весят меньше, чем изначальные.
6. Опубликовать образ на Docker Hub
После этого образ получит название согласно текущей версии приложения в mix.exs, количеству git-коммитов и sha-хешу, например 0.1.0.253-158c4a45c1
. Полное имя образа будет таким: teamon/demo:0.1.0.253-158c4a45c1
.
Существует также команда mix docker.shipit
, выполняющая сразу и сборку, и подготовку релиза, и публикацию образа.
Настройка загруженных в Docker приложений
Так как релизы в продакшн не содержат Mix, то наиболее простой способ подобрать рабочие настройки – использовать переменные среды. Стандартные образы Docker, созданные с помощью mix_docker, содержат конфигурацию REPLACE_OS_VARS=true
, поэтому нужно будет «подготовить» файл config/prod.exs
следующим образом:
Подробнее об этом можно почитать в
Не забудьте перестроить образ после изменения конфигураций!
Запуск приложения
Теперь можно смело запускать приложение, как простой Docker-контейнер.
Использование удалённого терминала
Так как Docker-контейнеры самодостаточны, то, чтобы подключиться к работающей ноде, используя remote_console, нужно выполнить команду exec с текущим контейнером:
Вот и всё!
Одно из явных преимуществ использования переменных среды для настройки приложений во время выполнения – это возможность использования одного и того же образа как на стадии подготовки, так и на стадии внедрения (изменяются только домены, API-ключи и т. д.), что очень удобно во время деплой в продакшн.
В следующей части рассказывается о том, как осуществить деплой этих же Docker-контейнеров с помощью Rancher и соединить несколько экземпляров в один Erlang-кластер.