[翻訳] Announcing Distillery 2.0

_この記事は [Announcing Distillery 2.0](https://dockyard.com/blog/2018/08/23/announcing-distillery-2-0) の翻訳記事になります。Distillery 2.0の新機能や改善点を知る上で素晴らしい記事だったので、筆者である [Paul Schoenfelder](https://twitter.com/gotbones) 氏に許可をいただき、翻訳を行うことにしました。理解不足のために訳が間違っている箇所があるかもしれませんが、その際はコメントで指摘していただくかPRをいただけるとありがたいです！_

# Distillery 2.0の発表

[Distillery](https://github.com/bitwalker/distillery) を2.0でどの方向へ導くか、そしてElixir coreのreleaseのためにどのように道を切り開くか、という点について述べた前回の [更新](https://dockyard.com/blog/2018/02/28/elixir-deployment-tools-update-february-2018) から数ヶ月が経過しました。想定していたよりも時間がかかりましたが、どのように落ち着いたか、そしてこれからどのように向かっていくのかをついにコミュニティで紹介できることを嬉しく思います。

2.0は既にHexでリリースされ、そのアップグレードガイドが [README](https://github.com/bitwalker/distillery/blob/master/README.md) に記載されています。 [ドキュメント](https://hexdocs.pm/distillery) も大幅に改訂され、Distilleryの機能だけではなく一般的なデプロイに関する新しいガイドも含めた多岐に渡るものとなっています。CHANGELOGの確認は、 [ここ](https://hexdocs.pm/distillery/changelog.html) から行うことができます。

主な変更は以下の通りです。

* ランタイム設定(runtime configuration)問題に対するソリューション
* ホットアップグレード/ダウングレード周りの体験の向上。カスタム [appups](http://erlang.org/doc/man/appup.html) のサポート向上、およびその動的な変更
* PIDファイル生成のサポート
* カスタムコマンドとフックのためのより良い一貫したプリミティブ(primitive)
* CLIで表示されるフィードバックとエラーの改善
* ドキュメントの大幅な改善: 新しいガイド、構造の改善、文書の検索など

それぞれの内容について詳細を見てみましょう。

## 設定プロバイダ(Config Providers)
現状、新規ユーザーとベテランユーザーの間で最も大きな問題となっているのは、ランタイム設定にどのように対処するかということです。適切に設計されたアプリケーションはランタイムで容易に設定を行うことができますが、これが問題となり、かつ現在最も苦難な点となっているのが依存(dependencies)に対処するということです。厳密に言えば、ブート時に主にアプリケーション環境を通して設定値が提供されることを期待する依存です。

あなたのアプリケーションそのものは、これらの依存がブートする前にコードを実行する機会を持っていないので、ランタイム設定を注入するチャンスがありません。そのため、この問題に対するいくつかの回避策を用いる必要があります。例えば、システム環境から値を注入するために `REPLACE_OS_VARS` を設定する; `included_applications` に依存を追加し、依存のライフサイクルを利用してスタート前に設定を行う;もしくは、可能であれば、依存から提供される `init` コールバックを利用してそれらの依存のスタートアップ時に初期設定を変更する; などといった方法です。

設定プロバイダはこの問題を解決するために設計されています。releaseがブートする前の設定のプロビジョニングを抽象化し、特別な回避策無しでrelease内の全てのアプリケーションがランタイムにおいて完全に設定されるようにしています。


### 設定プロバイダとは何か?

設定プロバイダ自身は、単に `Mix.Releases.Config.Provider` ビヘイビアを実装したElixirモジュールであり、release設定ファイルから与えられる引数のリストを受け取る `init/1` を含んでいます。これが呼び出された際、プロバイダはいくつかのソースから設定を読み出し、結果として生じる設定値をアプリケーション環境へと反映します。

設定値のフォールバックや上書きを行うために、設定プロバイダを積み重ねることも可能です。設定プロバイダはリリース設定ファイルで定義された順序に従って実行され、最後に実行されたものが優先されます。

### どうやって使うのか?

これらがどのように使用されるのかを理解するために、例を考えてみましょう。Distilleryは `Mix.Config` を最初から提供しています。これを使用するために、releaseを以下のように設定する必要があります。

```elixir
release :myapp do
  set version: current_version(:myapp)

  set config_providers: [
    {Mix.Releases.Config.Providers.Elixir, ["${RELEASE_ROOT_DIR}/etc/config.exs"]}
  ]

  set overlays: [
    {:copy, "rel/config/config.exs", "etc/config.exs"}
  ]
end
```

この設定は、releaseで使用する `Mix.Releases.Config.Providers.Elixir` プロバイダをセットアップします。これは、ランタイムでロードするべき設定ファイルのパスを示す1つの引数を受け取ります。パスは(上で示した `RELEASE_ROOT_DIR` のように)システム環境変数の参照を含めることが可能であり、プロバイダが実行されるランタイムでこの値が展開されます。

注: 環境変数の展開は `Mix.Releases.Config.Provider` モジュールの一部のヘルパー関数として利用可能ですが、引数としてパスを受け取るプロバイダの実装により使用されなければいけません。構文は同じですが、 `REPLACE_OS_VARS` の機能とは関係 _ありません_。これは設定がアクティブか否かに関わらず動作します。

`rel/config/config.exs` を `etc/config.exs` にコピーするoverlayによって設定ファイルが指定された場所に存在することを保証します。また、パスはreleaseのルートの相対パスで指定します。

注: 最終的な設定をrelease自体に含めることは必須ではありません。それは別のステップで用意した方がいいですが、 `Elixir` providerは、たとえ空であっても設定ファイルがそのパスに存在することを期待します。別のプロバイダは設定が存在しないことを別の方法で扱うかもしれませんが、指定されたパスが存在しない場合は、設定の問題がアプリの起動の起動を防げるようfailとすることが推奨されています。

よくあるPhoenixアプリの `config.exs` ファイルは次のようになるかもしれません。

```elixir
use Mix.Config

config :myapp, MyApp.Repo,
  username: System.get_env("DATABASE_USER"),
  password: System.get_env("DATABASE_PASS"),
  database: System.get_env("DATABASE_NAME"),
  hostname: System.get_env("DATABASE_HOST")

port = String.to_integer(System.get_env("PORT"))
config :myapp, MyAppWeb.Endpoint,
  http: [port: port],
  url: [host: "localhost", port: port],
  root: ".",
  secret_key_base: System.get_env("SECRET_KEY_BASE")
```

私達がラインタイムで変更されるべき値だけをどのように指定しているかがわかるでしょう。あなたはプロジェクトの `config/` 以下にある全ての設定ファイルを使用することもできますが、それらはコンパイルタイムの設定とデフォルト値のためだけに使用するべきです。コンパイルタイムとランタイムの区別をより明確にするため、releaseの設定をランタイム設定から切り離して後者を `rel/config` に格納することが推奨されています。

### どのように動作するか

設定プロバイダは、releaseがブートする前のプリブート(pre-boot)フェーズで、指定された順序で実行されます。プロバイダは自身のVMインスタンスの中で実行され、設定がプロビジョニングされた後にそれは終了し、release自体の `sys.config` へと設定が永続化されます。この環境はreleaseがロードした全てのアプリケーションを持っているため、それらを利用することが可能です。ただし、`:kernel`、 `:stdlib`、 `:compiler`、 そして `:elixir` だけがスタートします。

この専用の環境は、プロバイダに `:kernel` のようなアプリを設定することを可能とします。これはいくつかの便利なランタイム設定を含んでいますが、Providerにとって実行するにはあまりにも制限されている環境で開始します。それに加え、設定のロードを助けるために `:inets`、 `:crypto`、 `:ssl` などといったアプリケーションをプロバイダが開始することを可能にします。

注: 設定プロバイダの中で他のアプリケーションを開始することができたとしても、それらのアプリケーション自身が実行するための設定を必要とする場合、それらを開始する前にプロバイダの中であなた自身が設定を行わなければいけません。

全ての設定プロバイダが実行され、それらの設定がアプリケーション環境へと格納(`Application.put_env/3`とともに)されると、Distilleryは全体のアプリケーション環境を `sys.config` に永続化し、設定フェーズのVMを終了させます。この時点で、起動時にシステムを完全に設定するため、生成された `sys.config` を使用して "本当の" release VMを起動します。

この設計の結果として、設定の中で関数のキャプチャを行うことができなくなっています。以前にreleaseを使用したことがあるのであればこの点にすでに詳しいと思いますが、もしそうでなければ、関数のキャプチャではなく `{module, function, args}` (MFA) タプルとして設定値を格納するアプローチが推奨されます。

これは2つの理由によります。1つは、関数のキャプチャはキャプチャされた際の特定のバージョン固有のものであり、アップグレードをした際にキャプチャが有効なものではなくなってしまい、結果として `:badfun` エラーが発生します。2つ目は、ホットアップグレードが行われた際に、関数のキャプチャはキャプチャされた時点のコードのバージョンを参照するという点です。アップグレードされたコードはキャプチャされた関数を呼び出す際に最新バージョンを参照するを期待していますが、期待するものとは別の形の結果が返されるために失敗する可能性があります。それに加え、古いコードがシステムから消去されると、キャプチャは存在しないコードを参照してしまい、呼び出された際にやはり `:badfun` を発生させます。

MFAタプルの使用は、それらがシリアライズ可能であることを保証し、呼び出されたときに常に最新バージョンのコードを参照します。これにより、必要に応じてそれらを代わりに使用するように設定を設計します。

設定プロバイダ設計によるもう一つの結果は、あなたの設定は起動時に一度具体化され、その後は静的となるという点です。(ホットアップグレードを除きます。これは、アップグレードプロセスの標準的な部分として、設定が再評価される1つのケースです)

あなたのアプリケーションは、必要な時にアプリケーション環境から直接設定を取り出すよりも、起動時に設定を受け取り、アプリケーション環境から読み込んで、それをSupervisorツリーへと渡すように設計されるべきです。このルールを強制する要素はありませんが、設定プロバイダはこのアプローチを念頭において設計されており、releaseがブートされた後に動的に設定をフェッチすることは意図されていません。

### 参考文献

Distilleryの [ドキュメント](https://hexdocs.pm/distillery) では、JSONファイルに基づいたサンプルプロバイダを使用して、ランタイム設定と設定プロバイダを取り扱うセクションがあります。

また、一般的な設定に関するガイダンスも見つけることができ、アプリケーションのenvから設定を直接読み込むのではなく、ルートSupervisorからSupervisorツリーを下って設定をプッシュするアプリケーションの構築に関する例もあります。

もしあなたがElixirではない設定ファイルのフォーマットに興味があるなら、最近私はElixirのための [TOML](https://github.com/toml-lang/toml) ライブラリである [toml](https://github.com/bitwalker/toml-elixir) を作りました。これはTOMLファイルの設定プロバイダを含みます。

注: もしあなたが私の [Conform](https://github.com/bitwalker/conform) ライブラリのユーザーであれば、 `toml` のために廃止予定とすることをお伝えします。TOMLはConformが基づいていたinit-style設定形式の形式化された仕様であり、現在はDistilleryの設定プロバイダで、Conformでできることは事実上すべてTOMLで行うことができます。

## ホットアップグレード/ダウングレード

設定プロバイダがこのリリースにおいて重要な点である一方、それ以外にも私が紹介したいクォリティ・オブ・ライフの向上がいくつもあります。そのうちのいくつかはホットアップグレードに関するものであり、それはつまり [appup files](http://erlang.org/doc/man/appup.html) の操作と生成です。

### 新たなmixタスク - release.gen.appup

まず1つ目の改善点として、新しいMixタスク `release.gen.appup` の追加があげられます。これを使うことで、特定のアプリケーションとバージョンのペアのappupファイルを生成することができます。このファイルはDistilleryがその場で生成するものと同等ですが、出力先は `rel/appups/<app>/<v1>_to_<v2>.appup` となります。

Distilleryは、特定のアプリケーションとバージョンのペアを記述したappupsを `rel/appups` から探し、一致するものが見つかれば新しいものを生成する代わりにそのappupを使用します。これにより、必要に応じてこれらのappupsを変更して、アップグレードするアプリケーションにより適合させることができます。

以前はappupファイルを適切な場所に手動で配置する必要がありましたが、これはわかりやすいものではなく、また誤って削除される傾向があったため、ExrmとDistilleryでappupを使用して作業することは、これまで長い間苦痛でした。願わくば、この新しいタスクがより気持ちのいいアップグレード体験を可能にしてくれるでしょう！

### Appup変換

この分野におけるもう1つの大きな改善点は、別の形の拡張性、appup変換の導入です。これらは、appup命令セットを手作業ではなくプログラムで変換するように設計されたプラグインです。

Appup変換は、命令セットの拡張、使用される命令の変更、命令の削除や置換などに使用可能であり、あなたが実施したいと思う変換は基本的に全てサポートされています。

実際のところEdeliverは [relup patching](https://github.com/edeliver/edeliver/blob/master/docs/relup-patching.md) という似たような機能を持ってるのですが、少し異なる動作をします。私の理解では、既存の "relup patching" プラグインはappup変換に移植されますが、もしこれを使ってできるかもしれないことに興味があるのであれば、上のリンクで現在実際に使用されている変換のリストを確認することができます。

以下は、no-opのappup変換のシグニチャです。(これは命令セットを変更しておらず、単にそのまま返すだけです)

```elixir
defmodule MyApp.MyAppupTransform do
  use Mix.Releases.Appup.Transform

  def up(_app, _v1, _v2, instructions, _opts) do
    instructions
  end

  def down(_app, _v1, _v2, instructions, _opts) do
    instructions
  end
end
```

そしてこれがreleaseで使用する方法です。

```elixir
release :myapp do
  set appup_transforms: [
    {MyApp.MyAppupTransform, [] = _opts}
  ]
end
```

Appup変換のようなツールによって、コミュニティが自身ライブラリや他のツールのAppupと変換を共有できるようにすることを望んでいます。これにより、最も複雑なアプリケーションであっても、Distilleryで生成されたホットアップグレードを適切な処置をする上で信頼できるようになります。

## PIDファイル

このリリースにおいてクオリティ・オブ・ライフを向上させるもう１つの点は、起動時にPIDファイルを作成する機能です。PIDファイルは、それを生成した実行ファイルのPIDを含むファイルです。アプリケーションが終了すると、そのファイルは削除され、アプリケーションの実行中にそのファイルが削除されると、アプリケーションは終了します。アプリケーションがリスタートすると、ファイルに新しいPIDが書き込まれます。

これらのファイルは、特にsystemdなどのシステム監視プログラム(system supervisors)が、その監視下のサービスをよりよく監視、対話するために使用されます。一般的には、systemdの下で実行する場合は `foreground` を使用することをお勧めしますが、 `start` を通じてデーモンとしてサービスを実行した上でsystemdにそれを監視させたい場合、PIDファイルのサポートは以前のリリースよりも優れたインテグレーションを提供します。

PIDファイルの生成を有効にするには、システム環境変数として `PIDFILE=path/to/pidfile` をエクスポートするか、 `vm.args` か設定内で `-kernel pidfile "path/to/pidfile"` をセットします。(PIDファイルマネージャーはカーネルプロセスとして開始されるので、私たちは `:kernel` を使って設定します)

これらのいずれかが設定されると、PIDファイルマネージャーのプロセスは、起動時に現在のPIDを指定されたパスへ書き出します。そして、ファイルが削除された場合にノードを終了させたり、正常なシャットダウン(graceful shutdown)の間にファイルを削除できるよう、そのファイルの変更を監視します。

注: ノードを強制的に終了させた場合、プロセスはいかなるクリーンアップ処理も行うチャンスが無いためにPIDファイルはそのまま残ります。しかし、そのようなシャットダウンはいくつもの理由からお勧めできません。そのうち１つは、リソースが放置される可能性があることです。releaseが再開されたときにPIDファイルがまだ存在する場合、PIDは新しいPIDで上書きされますが、systemdのような外部プロセスの混乱を招く可能性があります。

## Read-Onlyモード

特定のユーザーとして実行するようにreleaseを実行するのは一般的なことであり、通常、権限は非常に厳しく制限されています。しかし、実行しているものとは _別の_ ユーザーとして、実行しているreleaseとやりとりしたり、あるいはreleaseの一部のコマンドを実行したいことがよくあるでしょう。

これまでは、Distilleryはシェルスクリプトが呼び出されるたびにいつも同じ初期化コードを実行していました。この初期化コードは、releaseに関連したディスク上のファイルを変更したり書き直したりするものです。(主に `sys.config` と `vm.args`) もし昇格したユーザーとしてコマンドを実行してreleaseをスタートしたとしても、オーナーが異なるため、アクセス可能と予想していたファイルを読み込めなかったり変更できなかったりして失敗してしまいました。

この問題を緩和するため、Distilleryはシェルスクリプトを "read-only" モードで操作させるための環境変数 `RELEASE_READ_ONLY` をエクスポートできるようにしています。これがセットされている場合、スクリプトはディスク上のどのファイルにおいても書き込みと変更をスキップします。注意点としては、あなたは少なくとも１回はこのモード無しでreleaseを実行しておかなければなりません。こうすることで、 `vm.args` や `sys.config` などといったreleaseのために必要なファイルができあがります。

将来的には、これが全面的に不要となることを望んでいます。この問題が発生する理由は、Distilleryがrelease内の「元の」ファイルを変更しないようにするため、最初の起動時にファイルを変更可能なディレクトリにコピーして、元のファイルに変更が無いようにしているためです。

これは、 `REPLACE_OS_VARS` がランタイム設定を注入する主な手段であった場合にはクリティカルでした。置換が最初に実行されると、 `sys.config` （または `vm.args`）の "変数" が失われ、将来の設定変更が有効とならないためです。オリジナルをコピーしてからそのコピーを置換することで、私たちは常に変数の置換に使うソースバージョンを持っています。

変換プロバイダによって、 `sys.config` のための `REPLACE_OS_VARS` は不要となり、完全な "read-only" の実行へと一歩近づくことができました。最後の障害は "vm.args" であり、同等なプロバイダメカニズム(もしくはサポートする拡張された設定プロバイダ)を私たちはまだ持っていません。

## CLIの改善

コマンドラインインターフェースは多くのバグ修正と小さな改善が行われ、特にエラーハンドリングが改善しました。ここでその全てについて言及することはしませんが、よりスムーズでフレンドリーな体験を期待していいでしょう。

注: 私はわかりにくい(unfriendly)エラーや汚いアウトプットは(修正可能なものであれば)バグであると考えているので、そのようなものを見つけたらissueを作ってください！

### rpcとeval

CLIにおける2つの大きな改善は、`rpc` と `eval` の動作が新しくなったという点です。 **これは破壊的な変更(breaking changes)** ですが、それらのコマンドをはるかに使いやすく、多用途なものにします。

以前は、 `rpc` と `eval` はどちらもリモートノードで対話していました。`rpc` コマンドは `rpc <module> <function> [arg1...]` という形で引数を受け取るのに対し、 `eval` は `eval '<string of code to evaluate>'` となります。それに加えて、 `rpcterms <module> <function> '<string representation of argument list>'` と `command <module> <function>` があります。これらのコマンドにはいくつもの問題がありました。

* これらは同じタスクを実行する冗長なバリエーションである
* ElixirではなくErlangの構文を使用している
* どのコマンドでどの構文を使用するのか覚えるのが困難である
* シェルの中で引数を表現するのが困難である(適切なエスケープなど) - Elixirシェルでちょっと時間がかかる単純なコマンドを試そうとすると、よく不満を感じることがある

これらの問題に対処するため、このコマンドは2.0で完全に修正されました。

* `rpc` はリモート評価のために使用される
* `eval` はローカルの評価のために使用される (VMの新しいインスタンスでコードを実行する)
* `rpc` と `eval` は評価のためにElixirのコードを文字列として受け取るか、 `--file path/to/script.exs` という形で評価するソースコードを与えられる
* `rpc` と `eval` は `--mfa "Module.fun/arity"` で呼び出すことも可能であり、コマンドラインで引数を指定して関数を呼び出すことができる。デフォルトでは1対1にマッピングされるが(引数の数はアリティとマッチしていなければいけない)、 `--argv` を全ての引数をリストとして指定された関数に渡すこともできる。(ただし1つのアリティを持っていなければいけない)
* `rpcterms` は削除された
* `command` は非推奨(deprecated)となったが、まだ削除はされていない

それに加え、 `rpc` と `eval` はどちらも `Application.load/1` をする必要なくreleaseで利用可能な全てのコードを持っています。(`command` も同様ですが、不要となったため将来的に削除されます)

### コマンドハンドリングの修正

これまで内部的にescriptで実装されていたすべてのコマンド処理がElixirで記述され、自動テストと共にDistillery自体に移行されました。これにより、保守と検証が簡単になります。その変更に加え、より良いエラーと役に立つ出力を提供するためUIが大幅に改良されました。

### 新コマンド: info

`info` という新しいコマンドもあります。このコマンドは現状では `info processes` という1つのオペレーションのみをサポートしています。これはObserverで見るようなreleaseのプロセスのリストを表示するもので、出力をソートするための様々なオプションを使用することができます。詳細については `bin/myapp help info processes` を実行して確認してください。将来的には、 `info` コマンドを拡張してObserverのような機能をそのまま提供できるようにすることを望んでいます。

### カスタムコマンドのためのより良いツール

これまでに自分用のカスタムコマンドを書いた経験があるなら、おそらくこのようなことをしていたでしょう。

```shell
#!/usr/bin/env bash

"${RELEASE_ROOT_DIR}"/bin/myapp command 'Elixir.MyApp.Tasks' foo -- arg1 #...
```

これは様々な理由で理想的なものではありませんが、主な問題は、セットアップが既に実行されている時に `bin/myapp` スクリプトを再起動(reinvoking)することで、そのスクリプトの環境をセットアップするために重複した無関係の作業をいくつも実行してしまうという点にあります。

代わりにもっと楽をするために、私は `release_ctl` と `release_remote_ctl` というヘルパーを追加しました。後者は前者のエイリアスですが、実行しているreleaseに接続するために必須な `--name` と `--cookie` フラグの受け渡しの面倒を見ます。

```shell
#!/usr/bin/env bash

# Local evaluation
release_ctl eval 'IO.inspect("hello world!")'
# Local evaluation by applying arguments to the function specified as a flat
# list, i.e. the same way Mix tasks receive arguments
release_ctl eval --mfa 'MyApp.Tasks.run/1' --argv -- "$@"
# Same as above, but rather than passing a list of arguments to the function,
# the number of arguments must match the arity of the function, and arguments
# are applied in those positions. If the number of arguments given does not
# match the arity, then a friendly error is displayed
release_ctl eval --mfa 'MyApp.Tasks.run/2' -- "$1" "$2"
# Remote evaluation versions of the above
release_ctl rpc 'IO.inspect("hello world!")'
release_remote_ctl rpc --mfa 'MyApp.Tasks.run/1' --argv -- "$@"
release_remote_ctl rpc --mfa 'MyApp.Tasks.run/2' -- "$1" "$2"
```

引数無しで(カスタムコマンドから) `release_ctl` を実行するか、 `bin/myapp help` を実行することで利用可能なコマンドとオプションの全てのリストを見ることができます。

これら2つのコマンドは、メインのreleaseスクリプトの再起動を避け、パフォーマンスの向上と容易なデバッグを提供します。

既に知っているものと同等の機能を持つ `erl` と `elixir` ヘルパーもまた利用可能ですが、releaseコンテキスト(releaseの全てのアプリケーションがロードされた)の中で実行します。これらは、独自のCLI実装で処理したいプリミティブやコマンドを構築する場合に便利です。

## ドキュメントの改善

[docs](https://hexdocs.pm/distillery) は [MkDocs](https://www.mkdocs.org/) を使って大幅に改訂されました。ナビゲーションがより簡単になり、Tipsや注意点をasideやコールアウトに抽出したことで読みやすくなり、さらにそれらは全て検索可能です！

改善は表面的な部分に留まらず、いくつもの新しいガイドの追加、全ての既存ページの更新、必要に応じた分割や統合が行われました。

具体的には、以下のガイドが追加されました。

* [Deploying To AWS](https://hexdocs.pm/distillery/guides/deploying_to_aws.html) - このガイドは、完全に自動化されたインフラのAWSに対してサンプルアプリケーションをデプロイする手順を説明しています。インフラ自体はCloudFormationで定義されており、Iac(Infrastructure as Code)の原則に従っています。
* [Working With Docker](https://hexdocs.pm/distillery/guides/working_with_docker.html) - このガイドでは、プロダクション設定でデプロイ可能なimageを構築するためのローカルDocker環境のセットアップの手順を説明します。最終的には、PostgreSQLやRedisなどの他のサービスも含め、1つのコマンドでアプリケーションの構築と実行が可能なDockerコンテナのセットアップを手に入れます。
* [Deploying To Digital Ocean](https://hexdocs.pm/distillery/guides/deploying_to_digital_ocean.html) - _Working With Docker_ を終えた上で、このガイドはDigital Oceanにおいてコンテナ化された環境へと簡単に展開し、Docker imageを実行する方法を説明します。

私はさらにWindowsのためのガイド設置に取り組んでいますが、準備が整うまでにこなさなければいけないいくつかの作業があります。これらのガイドがElixirのデプロイを分かりやすく説明するのに役立つことを私は願っています！

ベテランや初心者の皆さんには、 [Handling Configuration](https://hexdocs.pm/distillery/config/runtime.html) を読むことをお勧めします。これは、ランタイム設定に関する新しい変更点を詳細に理解するのに役立ちます。また、このガイドでは、アプリケーションを簡単に構成およびテストできるように設計するためのヒントも提供しています。

## これからの取り組み

今年の主な目標は、Elixirのコアツールにreleaseをもたらすことでした。その作業の最初のスコーピングでは、設定(config)がその努力の大きな障害となることがわかりました。これは、releaseの機能が設定を扱うOTPの部分と深く絡み合っているためです。

Distillery 2.0では、コアチームと私自身が設定のソリューションがreleaseとともにどのように機能するかを確認できるように計画されました。これはフィードバックを収集するだけでなく、Distilleryがすでに存在し、専門知識とアプリケーションを使用できるユーザープールを持っているという事実に頼ることができ、彼らの問題が解決されているかどうか、設定のソリューションが正しい方向性であるかどうかの判断を助けてくれます。

現在2.0はリリースされたので、私はフィードバックを収集することに努め、それをコアにおけるreleaseの初回実装のための最終提案へ反映することになるでしょう。コアチームがその提案に納得したら、重要なrelease機能をElixir自体に移す作業を開始します。

私は、コアツール周辺で注力している、いくつかの計画されたDistilleryの改善点があります。そのうち1つは、 `mix run` の同等機能の構築であり、これはMixではなくMixプロジェクトを実行するためreleaseプリミティブを使用します。基本的に、 `mix release.run` タスクは `mix run --no-halt` のように動作します。私はこのおおまかな設計を持っていますが、実装の時間を作るためにこの今回のリリースを待っていました。

これらのツールを改善するためのフィードバックや提案はどんなものも歓迎します。どのようなフィードバックも、私自身の考えにあるギャップの把握に役に立ちますし、既存の問題に対してどのように対処するかというアイデアも生まれます。

## このリリースに無いもの

2月のアップデートの時点で、クロスコンパイルがいまだに懸念事項であることを述べました。この点は変わっておらず、このリリースには解決へと導く有意義な進展はありません。

いくつかの選択肢について調べてみましたが、現時点で満足できるものは得られていません。この点に関するアイデアや提案があれば歓迎します。この問題にコードで取り組むことに興味がある場合はなお素晴らしいです！NervesのようなツールチェーンアプローチをDistilleryに統合するという実験を誰かが試すことに特に興味がありますが、Nerves自体の域を超えて、その方向性には何の取り組みも見えていません。(そして私自身まだ時間がありません)

## まとめ

私は、あなたが新しいリリースを試すことを楽しみにしていると願っています！どんなフィードバックも嬉しいので、そのためなら自由にissueを作ってください。問題に出くわした場合は特にです。

releaseやDistillery、そしてそれらのツールの将来について話たい場合は、ElixirConfとBig Elixirで話すことができます。

_DockYardは、優れたユーザーエクスペリエンス、デザイン、フルスタックエンジニアリング、Webアプリケーション開発、ソフトウェア、Ember、Elixir、Phoenixサービス、コンサルティング、トレーニングを提供するデジタル製品代理店です。_