こんにちは クラウド経費開発チーム ・ クラウド債務支払開発チーム の 宮村(みやむー) @miyamura.koyo です。
本業で Rails エンジニアをやる傍ら、コミュニティ の方で Elixir (フロントエンドも含め)で Web 開発を行っています。
最近では入門向けの書籍も充実してきたので、ご興味あればぜひ動かしてみてください! gihyo.jp
今回は Elixir で Web 開発している最中に得た知見をご紹介します。
対象バージョン
Elixir 1.16.2 OTP 26
IEx.pry
Elixir には標準で IEx.pry/0 という関数が提供されています。
これは Ruby on Rails の binding.pry や binding.irb と同じようなもので、動作中のアプリケーションを一時停止して、そのスコープで iex を操作できます。
defmodule Adder do def add(a, b) do c = a + b # 追加 require IEx IEx.pry() end end
$ iex adder.exs Erlang/OTP 25 [erts-13.0.4] [source] [64-bit] [smp:16:16] [ds:16:16:10] [async-threads:1] [jit:ns] Interactive Elixir (1.14.3) - press Ctrl+C to exit (type h() ENTER for help) iex(1)> Adder.add(1,2) Break reached: Adder.add/2 (adder.exs:6) 3: c = a + b 4: # 追加 5: require IEx 6: IEx.pry() 7: end 8: end pry(1)> a 1 pry(2)> b 2 pry(3)> c 3
dbg
また最近では dbg コマンドというデバッグにより特化した関数もリリースされています。 以下ドキュメントで動画付きで解説されているのでご覧ください。
pry や dbg していると Docker 環境で起動した elixir アプリケーションで動作しない
以前、Qiitaで執筆した記事では Docker で Phoenix のローカル環境構築を行う方法を紹介しました。
しかしこれだとうまく pry や dbg が動作しませんでした。
動作させるには一工夫必要です。
Docker 環境でも動作させる方法 docker attach
IEx.pry を動作させる方法
まず先ほど紹介した Qiita 記事から以下のようにして Phoenix アプリケーションを起動しているとします。
services: web: ... command: "mix phx.server"
これを以下のように書き換えます。iex コマンドで起動させます。
※ Elixir 1.16.2 だと iex コマンドに変更しなくても動作しました。ただし後述する dbg コマンドを動かすには結局 iex コマンドで起動させる必要があるため変更することをオススメします。
services: web: tty: true stdin_open: true ... command: "iex -S mix phx.server"
そしてコンテナを起動します。
起動後に docker attach
コマンドでコンテナにアタッチします。
これで準備完了です。あとは任意のコード位置に require IEx; IEx.pry()
を記述することで自由にデバッグできます。
$ docker compose up -d $ docker attach oauth_sample-web-1 [info] GET /users/log_in [debug] Processing with OauthSampleWeb.UserLoginLive.new/2 Parameters: %{} Pipelines: [:browser, :redirect_if_user_is_authenticated] Request to pry #PID<0.520.0> at OauthSampleWeb.UserLoginLive.mount/3 (lib/oauth_sample_web/live/user_login_live.ex:41) 38: def mount(_params, _session, socket) do 39: # dbg() 40: require IEx 41: IEx.pry() 42: email = live_flash(socket.assigns.flash, :email) 43: form = to_form(%{"email" => email}, as: "user") 44: {:ok, assign(socket, form: form), temporary_assigns: [form: form]} Allow? [Yn] Y Erlang/OTP 26 [erts-14.2.4] [source] [64-bit] [smp:16:16] [ds:16:16:10] [async-threads:1] [jit] Interactive Elixir (1.16.2) - press Ctrl+C to exit (type h() ENTER for help) iex(1)> socket.id "phx-F8xZO_VOo0B_cQVC
ハッカーっぽいですね!
Docker でも IEx.pry
でデバッグできるようになりました!
dbg を動作させる方法
dbg を動作させるにはもう一工夫必要です。 --dbg pry
オプションを渡してみましょう。
services: web: tty: true stdin_open: true ... command: "iex -S --dbg pry mix phx.server"
Elixir は 1.16.2 だと dbg コマンドがデフォルトでは pry コンソールを起動させないようになっています。
そのため iex --dbg pry
で起動させることで pry コンソールを起動させるようにする必要があります。
(古いバージョンだとオプションが違ったりするので、お使いの Elixir バージョンに合わせてドキュメントを探してみてください)
おまけ --sname をつけてアプリケーションを起動させる方法
ちなみに Elixir が提供する Node の仕組み(分散システム機能)を用いることで、別の方法でも実現できます。
実際にはあまり使う機会はないかもしれませんが、docket attach
コマンドを用いた手法がうまくいかなかったときには試してみてください。
まず先ほど紹介した Qiita 記事から以下のようにして Phoenix アプリケーションを起動しているとします。
services: web: ... command: "mix phx.server"
これを以下のように書き換えます。
services: web: ... command: "elixir --sname sample@web -S mix phx.server"
そしてコンテナを起動します。 この時、 iex セッションを先ほど命名した --sname に向けて接続します。 これで動作中の Phoenix アプリケーションに後付けで iex のセッションを接続することが出来ました。
docker compose up -d docker compose exec web iex --sname "pry@web" --remsh sample@web
※ コマンドの意味は ChatGPT くんに聞いてみるとわかりやすいです。
こんな感じで止まってくれます!
$ docker compose exec web iex --sname "pry@web" --cookie sample --remsh sample@web Erlang/OTP 26 [erts-14.2.4] [source] [64-bit] [smp:16:16] [ds:16:16:10] [async-threads:1] [jit] Interactive Elixir (1.16.2) - press Ctrl+C to exit (type h() ENTER for help) Request to pry #PID<0.544.0> at OauthSampleWeb.UserLoginLive.mount/3 (lib/oauth_sample_web/live/user_login_live.ex:41) Request to pry #PID<0.544.0> at OauthSampleWeb.UserLoginLive.mount/3 (lib/oauth_sample_web/live/user_login_live.ex:41) 38: def mount(_params, _session, socket) do 39: # dbg() 40: require IEx 41: IEx.pry() 42: ... 43: ... 44: ... Allow? [Yn] Y Interactive Elixir (1.16.2) - press Ctrl+C to exit (type h() ENTER for help) iex(sample@web)1> socket.id "phx-F8xXV_t49kiTNwbB"
まとめ
Docker で起動した Phoenix アプリケーションで IEx.pry や dbg を用いてデバッグする方法を紹介しました。
ちなみに筆者は Elxiir 1.14.5 環境でも動作させてみたのですが、微妙に挙動が怪しいので、Elixir 1.16.2 など現時点の最新で試すことをお勧めします!
また、プロジェクトの docker-compose.yml
を修正するのはちょっと...という人も docker-compose.override.yml
を使うことで、自分の手元だけ動作を変えることができるので、そちらを使ってみてください。
とっても便利なのでぜひ使ってみてくださいね。よい Elixir ライフを。
マネーフォワード福岡拠点では、エンジニアを募集しています!
色んな言語を経験しているエンジニアと働きたい方はぜひ!
福岡開発拠点のサイトもあるのでぜひみてください!