ElixirSeniorSystem design
Как развернуть приложение Elixir/OTP с помощью releases?
Mix releases собирают самодостаточный архив с BEAM, приложением и конфигом. Команды: mix release, затем _build/prod/rel/app/bin/app start. Конфигурация runtime через Config.Provider или releases config/runtime.exs.
Развёртывание Elixir/OTP с помощью Mix Releases
Mix Releases (добавлены в Elixir 1.9) создают самодостаточный пакет: BEAM runtime, скомпилированные .beam-файлы, конфигурацию и стартовые скрипты. Сервер не требует установки Elixir или Erlang.
Подготовка: mix.exs
defmodule MyApp.MixProject do
use Mix.Project
def project do
[
app: :my_app,
version: "1.0.0",
releases: [
my_app: [
include_executables_for: [:unix],
steps: [:assemble, :tar]
]
]
]
end
end
Runtime-конфигурация
Файл config/runtime.exs читается при каждом старте приложения (не при сборке), что позволяет использовать переменные окружения:
# config/runtime.exs
import Config
config :my_app, MyApp.Repo,
url: System.fetch_env!("DATABASE_URL"),
pool_size: String.to_integer(System.get_env("POOL_SIZE", "10"))
config :my_app, MyAppWeb.Endpoint,
secret_key_base: System.fetch_env!("SECRET_KEY_BASE"),
url: [host: System.fetch_env!("PHX_HOST"), port: 443, scheme: "https"]
Сборка release
# Локальная сборка (dev-режим)
mix release
# Production (обычно в CI/Docker)
MIX_ENV=prod mix release
# Артефакт:
# _build/prod/rel/my_app/
# Tar-архив: _build/prod/my_app-1.0.0.tar.gz
Dockerfile для production
# Dockerfile
FROM elixir:1.16-otp-26-slim AS builder
WORKDIR /app
COPY mix.exs mix.lock ./
RUN mix deps.get --only prod
COPY config/ config/
RUN MIX_ENV=prod mix compile
COPY lib/ lib/
RUN MIX_ENV=prod mix release
FROM debian:bookworm-slim AS runner
WORKDIR /app
COPY --from=builder /app/_build/prod/rel/my_app ./
ENV PHX_HOST=example.com SECRET_KEY_BASE=xxx DATABASE_URL=ecto://...
CMD ["bin/my_app", "start"]
Управление запущенным release
# Запуск в foreground
bin/my_app start
# Daemon
bin/my_app daemon
# Remote IEx shell к запущенному узлу
bin/my_app remote
# Eval (миграции БД)
bin/my_app eval "MyApp.Release.migrate()"
# Graceful stop
bin/my_app stop
Запуск миграций Ecto без Mix
# lib/my_app/release.ex
defmodule MyApp.Release do
def migrate do
{:ok, _} = Application.ensure_all_started(:my_app)
for repo <- repos() do
{:ok, _, _} = Ecto.Migrator.with_repo(repo, &Ecto.Migrator.run(&1, :up, all: true))
end
end
defp repos do
Application.fetch_env!(:my_app, :ecto_repos)
end
end
Подводные камни
- Release собирается под конкретную ОС и версию BEAM — собранный на macOS артефакт не запустится на Linux; всегда собирайте в Docker с целевой ОС.
- config/config.exs и config/prod.exs вычисляются во время компиляции, а не старта — переменные окружения там не доступны; используйте только config/runtime.exs.
- System.fetch_env!/1 в runtime.exs упадёт при старте, если переменная не задана — это желаемое поведение, но неожиданное в staging без полного .env.
- Флаг :tar в steps создаёт архив, но не удаляет несжатую директорию — в CI занимает лишнее место.
- Remote shell через bin/app remote требует совпадения cookie между строящим и запущенным узлом.
- include_executables_for: [:unix] не создаёт Windows .bat скрипты — важно при cross-platform CI.
- Mix.install/1 недоступен в release — все зависимости должны быть в mix.exs.
- Горячее обновление кода (appup/relup) совместимо с releases, но требует ручной генерации appup-файлов; ошибка в appup может привести к partial upgrade и несогласованному состоянию.
Common mistakes
- Сводить otp releases к названию метода без lifecycle и failure path.
- Игнорировать модель runtime: Elixir компилируется в BEAM bytecode и наследует процессы, message passing, supervision и hot-code friendly модель Erlang VM.
- Не отделять validation, authorization, transaction boundary и business logic.
- Не обсуждать idempotency, retries, shutdown и observability.
What the interviewer is testing
- Объясняет otp releases через конкретную точку lifecycle в Elixir.
- Приводит корректный минимальный пример без вымышленных методов или callbacks.
- Называет edge cases: пустые значения, ошибки, транзакции, безопасность или concurrency.
- Связывает решение с метриками, backpressure, retry policy и graceful shutdown.