DockerでElixirを簡単に動かすメモ(Windows上)

# DockerでElixirを簡単に動かす

　Elixirの勉強のために、Windows上にElixirを直接インストールせずに、Docker上でElixirを簡単に動かす方法を試したメモです。

　Windows上に直接インストールするには、InstallerのEXEファイルを動かすか、Chocorateyからインストールするのですが、EXEファイルのInstallerはProxyをうまくこえられなかったり、遅かったりしますし、ChocorateyでインストールするくらいないらDockerの方がいいやと思った次第です。

　Dockerは何かと便利なのでなるべく使うように習慣付けているというのもあります。

## 動作環境
 * Windows 10
 * Docker 1.11.2
 * Elixir 1.3.2(2016/08/28現在latest)

## DockerにPull

DockerのElixirのイメージを探して、下記のイメージがOfficalとあるので、これを利用します。

 * https://hub.docker.com/_/elixir/

DockerのOfficalのサイト(以下、サイト)にあるように下記のコマンドでPullします。

~~~
docker pull elixir
~~~

### iexの実行

インタラクティブなiexを実行します。バージョンの確認と"5 * 6"を計算してみます。
終了はCtrl+Cを２回か、Ctrl+Gの後、qを入力してReturnです。

~~~
$ docker run -it --rm elixir
Erlang/OTP 19 [erts-8.0.3] [source] [64-bit] [async-threads:10] [hipe] [kernel-poll:false]

Interactive Elixir (1.3.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> System.version
"1.3.2"
iex(2)>5 *
...(2)>6
30
iex(3)>
BREAK: (a)bort (c)ontinue (p)roc info (i)nfo (l)oaded
       (v)ersion (k)ill (D)b-tables (d)istribution
^C
~~~

Ctrl+G、q、Retrunの場合の終了。

~~~
$ docker run -it --rm elixir
Erlang/OTP 19 [erts-8.0.3] [source] [64-bit] [async-threads:10] [hipe] [kernel-poll:false]

Interactive Elixir (1.3.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)>
User switch command
 --> q
~~~

### ノード

まだ、Elixirを勉強中なので詳しいことが分かっていないのですが、サイトに`--sname`のサンプルが載っていたので、２つのノードを建てて実行できるか試してみます。もし、もっと良いやり方をご存知の方がいましたら、教えてください。
サイトには、`--sname`で１つのノードを動かす例しかなかったので、２つのノードが本当に動くのか試してみました。動かす２つのノードは同じコンピュータ上を想定しています。

まず、fooというノードでiexを実行します。

~~~
$ docker run -it --rm -h local elixir iex --sname foo --cookie sample
Erlang/OTP 19 [erts-8.0.3] [source] [64-bit] [async-threads:10] [hipe] [kernel-poll:false]
~~~

次に、barというノードを同じコンテナで実行したいので、`docker ps`コマンドでコンテナIDを取得します。

~~~
$ docker ps
CONTAINER ID  IMAGE  COMMAND                  CREATED        STATUS        PORTS  NAMES
8983d6071d8d  elixir "iex --sname foo --co"   12 seconds ago Up 8 seconds         furious_goldstine
~~~

barというノードでiexを実行し、fooにconnectしてみます。execで動かすのは、fooのコンテナ上でbarのノードを実行したいためです。runだと別のコンテナが起動してしまいます。

~~~
$ docker exec -it 8983d6071d8d iex --sname bar --cookie sample
Erlang/OTP 19 [erts-8.0.3] [source] [64-bit] [async-threads:10] [hipe] [kernel-poll:false]

Interactive Elixir (1.3.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(bar@local)1> Node.list
[]
iex(bar@local)2> Node.connect :"foo@local"
true
iex(bar@local)4> Node.list
[:foo@local]
~~~

fooからノードのリストを取得すると`bar@local`が追加されています。

~~~
Interactive Elixir (1.3.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(foo@local)1> Node.list
[:bar@local]
~~~

続けて、fooで関数を定義してみます。

~~~
iex(foo@local)2> defmodule Hello do
...(foo@local)2>   def world, do: IO.puts "hello world"
...(foo@local)2> end
~~~

barからfooで定義した関数を実行してみます。

~~~
iex(bar@local)5> Node.spawn_link :"foo@local", fn -> Hello.world end
hello world
#PID<9319.100.0>
~~~

無事、実行されて`hello world`が返ってきました。


最後に、ファイルに保存されたプログラムが実行できるか確認します。
ホームディレクトリの下の下記のようなパスを作って`cd`で移動し、`vim`で簡単なプログラムを書いて保存します。

~~~
MINGW64 ~/work/local/docker/elixir
$ vim sample.exs
IO.puts "Hello, World!"
~~~

サイトにあるコマンドを短くして、下記のコマンドで実行します。

~~~
$ docker run -it --rm -v $PWD:/app -w /app elixir elixir sample.exs
Hello, World!
~~~

ファイルに保存したプログラムも実行できることを確認できました。

Windows上のDockerでも動くことを確認できました。Elixirの勉強の参考になれば幸いです。また、もし、もっといい実行の仕方がありましたら教えてください。