Edeliverを使ってElixirアプリケーションをデプロイする

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

Elixirアプリケーションのデプロイツールはedeliverが一番人気のようです。
edeliverはRubyのCapistranoのようなツールです。
今回はedeliverを使ってPhoenixアプリケーションをEC2のサーバにデプロイします。

edeliverの仕組み

edeliverはビルド専用のマシンでアプリケーションをビルドし、productionサーバにデプロイします。
内部ではDistilleryというリリースパッケージを作成するツールを利用しています。
デプロイフローを図にすると以下のようになります。

edeliver

ビルドサーバには事前にErlang, Elixir, NodeJSをインストールする必要があります。

セットアップ

ssh-agentの設定

edeliverはversion管理にgitを使用します。
ビルドサーバでgitを使ってチェックアウトするためにssh-agentの設定が必要になります。
以下コマンドでssh−agentの設定を行います。

$ ssh-add -K 鍵のフルパスファイル名

依存ライブラリの追加

デプロイ対象のphoenixアプリケーションのmixファイルに追加します

  defp deps do
    [
      {:phoenix, "~> 1.3.0"},
      {:phoenix_pubsub, "~> 1.0"},
      {:phoenix_ecto, "~> 3.2"},
      {:postgrex, ">= 0.0.0"},
      {:phoenix_html, "~> 2.10"},
      {:phoenix_live_reload, "~> 1.0", only: :dev},
      {:gettext, "~> 0.11"},
      {:cowboy, "~> 1.0"},
      {:edeliver, "~> 1.4.4"}, ## これ
      {:distillery, ">= 0.8.0", warn_missing: false} ## これも
    ]
  end

ダウンロードします。

$ mix do deps.get, compile

設定ファイルの追加

プロジェクトルートに.deliver/config ファイルを追加します。
以下内容の設定を行います。

  • ビルドサーバとリリース対象サーバをそれぞれ設定する
    • ホスト名
    • ユーザー名
    • ビルドディレクトリ
    • リリースサーバのdeploy先ディレクトリ
  • prod.secret.exsファイルのビルドサーバでの取得先を指定します
    • パスワードを設定するファイルなのでリポジトリには追加しないファイルです
    • このファイルに後ほどsecret_key_baseとデータベース設定を記述します

ファイルは以下のようになります
(BUILD_HOST, PRODUCTION_HOSTに指定したサーバは ~/.ssh/config にも設定を追加します)

# .deliver/config

APP="deploy_test_app"

BUILD_HOST="build-server"
BUILD_USER="ec2-user"
BUILD_AT="/tmp/edeliver/deploy_test_app/builds"

PRODUCTION_HOSTS="production-server"
PRODUCTION_USER="ec2-user"
DELIVER_TO="/home/ec2-user"

# For *Phoenix* projects, symlink prod.secret.exs to our tmp source
pre_erlang_get_and_update_deps() {
  local _prod_secret_path="/home/ec2-user/builds/config/prod.secret.exs"
  if [ "$TARGET_MIX_ENV" = "prod" ]; then
    __sync_remote "
      ln -sfn '$_prod_secret_path' '$BUILD_AT/config/prod.secret.exs'
    "
  fi
}

pre_erlang_clean_compile() {
  status "Installing NPM dependencies"
  __sync_remote "
    [ -f ~/.profile ] && source ~/.profile
    set -e

    cd '$BUILD_AT/assets'
    npm install $SILENCE
  "

  status "Building static files"
  __sync_remote "
    [ -f ~/.profile ] && source ~/.profile
    set -e

    cd '$BUILD_AT/assets'
    mkdir -p priv/static
    npm run deploy $SILENCE
  "

  status "Running phoenix.digest"
  __sync_remote "
    [ -f ~/.profile ] && source ~/.profile
    set -e

    cd '$BUILD_AT'
    APP='$APP' MIX_ENV='$TARGET_MIX_ENV' $MIX_CMD phoenix.digest $SILENCE
  "
}

gitignoreに追加&コミット

ビルドサーバで作成したバイナリはローカルのディレクトリに保存されます。
(設定でS3に保存することもできます)

ディレクトリをgit管理の対象外にします。

$ echo ".deliver/releases/" >> .gitignore

そしてコミットします(コミットしないとデプロイできません)。

$ git commit -m "Setting up edeliver"

サーバPortの設定

config/prod.exs ファイルにサーバのport番号を設定します。
(phoenixアプリケーションはデフォルトで4000番を使います)

config :deploy_test_app, DeployTestAppWeb.Endpoint,
  load_from_system_env: true,
  http: [port: 4000],
  url: [host: "example.com", port: 80],
  server: true,
  cache_static_manifest: "priv/static/cache_manifest.json"

DistilleryのSetup

edeliverが内部で使用しているdistilleryの初期化を行います。

$ mix release.init

rel/config.exsファイルが作成されます。
再度コミットしてからpushします。

$ git commit -m "Setting up distillery"
$ git push origin master

secretファイルの編集

ビルドサーバにsshして prod.secret.exs ファイルを作成しsecret_key_base, database情報を設定します。
保存場所は先ほど作成した .deliver/config ファイルに記述している場所です。
設定項目は以下です。設定値はそれぞれアプリケーション固有の情報になります

use Mix.Config

config :deploy_test_app, DeployTestAppWeb.Endpoint,
  secret_key_base: "yoursecretkeybasecomeshere"

# Configure your database
config :deploy_test_app, DeployTestApp.Repo,
  adapter: Ecto.Adapters.Postgres,
  username: "yourdatabaseusercomeshere",
  password: "yourdatabasepasswordcomeshere",
  database: "deploy_test_app_prod",
  hostname: "yourdatabasehostcomeshere",
  pool_size: 15

ビルド&デプロイ

ここまででデプロイのための設定は終わりです。
コマンドを自端末で実行しビルド、デプロイしましょう。

ビルド

それではビルドします。
次のコマンドを実行するとビルドサーバでビルドが行われます。

$ mix edleiver build release production

master以外のブランチを指定する場合は--branchオプションを追加します。

$ mix edeliver build release production --branch=$BRANCH_NAME

デプロイ

次のコマンドで設定したプロダクションサーバにデプロイします。

$ mix edeliver deploy release to production

更新

初回デプロイ以降は以下のコマンドで更新します。

$ mix edeliver upgrade

DB作成

最初のデプロイの場合、アプリケーションで使用するデータベースを作成する必要があります。

$ MIX_ENV=prod mix ecto.create

データベースを作成したらmigrationを実行します。

$ mix edeliver migrate production

アプリケーション起動

以下コマンドでアプリケーションを起動します。

$ mix edeliver start production

お疲れ様でした。これでデプロイの一連の作業は完了です。

その他

リリース先のサーバでアプリケーションを起動、停止するにはアプリケーションのルートディレクトリで以下のコマンドを実行します。

$ ./bin/deploy_test_app start

(停止するときはstop、再起動するときはrestartです)

replで起動することもできます。調査の時に便利です。

$ ./bin/deploy_test_app remote_console

参考情報

edeliver
Deploying Elixir applications with Edeliver
Deploy Early and Often: Deploying Phoenix with Edeliver and Distillery (Part Two)