Phoenixコンテナと共にLivebookコンテナを起動して開発時に利用する
はじめに
PhoenixでWebアプリケーションを開発する際に、開発メンバー間で開発環境を揃えるためにdockerを利用するケースがあると思います。そのような場合に、Phoenixのコンテナと一緒にLivebookのコンテナを立てておくと色々と捗ります。
この記事ではPhoenixと一緒にLivebookのコンテナを用意して開発時に利用する流れについて解説します。
構成
雑な絵ですが、このような構成を作ります。
この記事の検証に作ったリポジトリも公開しています。参考にしてください。
docker準備
docker for mac利用時の一例を紹介します。以下などを参考にdocker環境は適宜読み替えていただいてOKです。
Dockerfileを作成する
次のようなdockerfileを作成します。
FROM hexpm/elixir:1.14.2-erlang-25.1.2-alpine-3.16.2
RUN apk add --no-cache --update \
bash \
inotify-tools \
git \
build-base \
nodejs \
npm
RUN mix local.hex --force && \
mix local.rebar --force
WORKDIR /app
docker-compose.ymlを作成する
docker-compose.yml
を次のように作成します。
version: "3"
services:
app:
build: .
volumes:
- .:/app
ports:
- 4000:4000
depends_on:
- db
# 1. ノード名とcookieをセットしてphoenixサーバーを起動する
command: "elixir --sname sample@app --cookie sample -S mix phx.server"
db:
image: postgres:14-alpine
ports:
- 5432:5432
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
volumes:
- dbdata:/var/lib/postgresql/data
livebook:
image: ghcr.io/livebook-dev/livebook
ports:
- 8080:8080
environment:
# 2. appコンテナのnode起動時の `--sname` と合わせる
- LIVEBOOK_COOKIE=sample
# 3. defaultでappコンテナ内のnodeにattachedされた状態にする
- LIVEBOOK_DEFAULT_RUNTIME=attached:sample@app:sample
# 4. 開発環境なのでtokenによる認証は不要なため無効化する
- LIVEBOOK_TOKEN_ENABLED=false
volumes:
dbdata: {}
ポイントは次のとおりです。
- Phoenix起動時に
--sname
と--cookie
を設定してlivebookからノード名とcookieを指定して接続できるようにします。 -
LIVEBOOK_COOKIE
という環境変数でLivebook起動時のcookieを設定します。これを1.
で--cookie
で指定した値と同じ値を設定します。 - Livebook起動時に最初からappコンテナ内のノードに接続した状態にします。これを設定することで、Livebookでnotebook作成後に毎回Runtime Settingsからの接続が不要になります。
- Livebookのデフォルトで有効になっているtokenベースの認証を無効化します。これはおまけです。
Livebook起動時の環境変数についてはREADMEにまとまっているため、詳細はそちらを参照してください。
プロジェクトの作成
コンテナを起動して、プロジェクトの雛形を作成します。
$ docker compose run --rm --no-deps app /bin/bash
# コンテナ内での作業
# archiveのインストール
bash-5.1# mix archive.install --force hex phx_new
# phoenixプロジェクトをカレントディレクトリに生成する
bash-5.1# mix phx.new . --app sample
The directory /app already exists. Are you sure you want to continue? [Yn] Y
# ... (略)
Fetch and install dependencies? [Yn] Y
* running mix deps.get
* running mix deps.compile
# ... (略)
dev.exsの修正
dev.exs
を次のように修正して、appコンテナへの接続と、appコンテナからdbコンテナへの接続が通るようにします。
# Configure your database
config :sample, Sample.Repo,
username: "postgres",
password: "postgres",
- hostname: "localhost",
+ hostname: "db",
database: "sample_dev",
config :sample, SampleWeb.Endpoint,
# Binding to loopback ipv4 address prevents access from other machines.
# Change to `ip: {0, 0, 0, 0}` to allow access from other machines.
- http: [ip: {127, 0, 0, 1}, port: 4000],
+ http: [ip: {0, 0, 0, 0}, port: 4000],
check_origin: false,
dev.exs
を修正したら、コンテナ内で mix ecto.setup
を実行します。エラーなくMigrationのログが出力されればOKです。
bash-5.1# mix ecto.setup
The database for Sample.Repo has been created
06:13:10.550 [info] Migrations already up
コンテナの起動
コンテナを抜けて、すべてのコンテナを起動します。
$ docker compose up -d
http://localhost:4000
にアクセスしてPhoenixのウェルカムページに、http://localhost:8080
にアクセスしてLivebookの画面にそれぞれアクセスできていればOKです。
Livebookの操作
続いて、Livebookの操作について試してみましょう。
新規ノートブックの作成
http://localhost:8080
からLivebookにアクセスします。右上の「New notebook」から新規ノートブックを作成します。
前述の通り、LIVEBOOK_DEFAULT_RUNTIME
を設定しているため、すでにappコンテナ内のノードへの接続設定が済んでいます。
問題なく接続できていれば、試しに次のコードを実行してみると "/"
が返ってくるはずです。このように、Livebookからappコンテナ内のノードに接続して、自由に関数を試すことができます。
SampleWeb.Router.Helpers.page_path(SampleWeb.Endpoint, :index)
DB操作を試す
Ectoの操作もできることを確認します。試しに Accounts.User
スキーマを生成してmigrationまで行います。
$ docker compose exec app mix phx.gen.schema Accounts.User users name:string email:string
$ docker compose exec app mix ecto.migrate
その後、Livebookからrepo操作をしてみると、クエリが発行されているのが確認できると思います。
Sample.Repo.all(Sample.Accounts.User)
recompile
livebookからMixプロジェクトをrecompileする場合は、IEx.Helpers.recompile/0
を実行すればOKです。
IEx.Helpers.recompile()
ノートブックを永続化する
docker-compose.yml
を修正してlivebookに特定のディレクトリをmountすれば、ホストとコンテナ間で .livemd
ファイルを読み書きできます。
試しに、次のように docs
ディレクトリをmountして、livebook起動時にマウントしたディレクトリをデフォルトで開くように設定します。
livebook:
image: ghcr.io/livebook-dev/livebook
+ volumes:
+ - ./docs:/data
ports:
- 8080:8080
environment:
- LIVEBOOK_COOKIE=sample
- LIVEBOOK_DEFAULT_RUNTIME=attached:sample@app:sample
- LIVEBOOK_TOKEN_ENABLED=false
+ - LIVEBOOK_HOME=/data
コンテナを立ち上げ直します。
$ docker compose down
$ docker compose up -d
コンテナ再起動後、http://localhost:8080
にアクセスすると、/data/
を開いた状態でLivebookにアクセスできていればOKです。
再度「New notebook」から新規ノートブックを作成後、右下の保存ボタンから以下の手順でファイルを保存します。
- 「Choose α file」をクリック
- ファイル名を入力
- 「Choose」をクリック
- 「Save now」をクリック
実行したノートブックをファイルとして保存してcommitしておき、別の開発者が同じノートブックを同様に開く といったワークフローが可能になります。
まとめ
Phoenixコンテナと合わせてLivebookコンテナを立ち上げて運用する手順について解説しました。作業ログをmarkdownとして残せるリッチなIExとして使ったり、開発のオンボーディングのドキュメントとして整備したり、いろいろな活用方法ができます。ぜひ活用してみてください。
Discussion
2023/11/25追記:
livebookのdocker imageのsourceが変更になっているとのことで、@mnishiguchiさんよりPRいただきました。ありがとうございます!記事内も併せて修正しています。
新しいLivebookでは、いつからかattachedにsnameが使えなくなっていました。
(本記事が結構前のものであるのは承知です。共有のためコメントします)
--name
にしてFQDN形にすれば良いみたいなので、LIVEBOOK_DEFAULT_RUNTIME=attached:sample@app.<network name>:sample
みたいな形にする必要がありました。
(<network name>はデフォルトでは、
フォルダ名+_default
)