LoginSignup
38
26

More than 3 years have passed since last update.

Julia の Jupyter Notebook を他人に試してもらうためのツールとして Binder を活用する

Last updated at Posted at 2020-02-06

本日は

  • Julia は Python に比べるとまだ人口が少ないので「こういうのをJuliaで作ったよ!」とSNSで宣伝するとみんな(Julia界隈)が喜びます.作ったらそれがSOTA(state of the art) なんです.ただし,動かす側からだとそのスクリプト,ノートブックを動かすのにそれをダウンロードして必要に応じてJupyter Notebookを立ち上げるという一手間が肉に塩を振る以上に手間がかかってしまうことです.環境を構築している間にSNSで動いてる!しゅごいいぃと感じた熱意が指数関数的に現象してしまいます.パッケージが入ってなくて途中でエラーを吐いて動かなくなったら尚更です.また,閲覧しているデバイスがパソコンとは限らないので可能ならスマホ,タブレットでみたユーザーがパソコンにログインして動かすというのも手間っちゃ手間です.

  • さて,グラフ描画ライブラリの Julia ラッパーを提供する GR.jl 開発者のツイートでこういうのがありました.

リンクをクリックするとbinderというアイコンが出てきて

image.png

Jupyter Notebook が見つかって

image.png

anim.ipynb を選択して動かすと

image.png

動くんですけど!!!,マジかブラウザ上でJulia動かせるんか! iPhone や iPad で動くんか!(実際に動きます).

ということで

  • Binder の使い方を紹介します.Binderを使うと既存の公開されているリポジトリにあるJupyter Notebookをブラウザ上で動かすことができます.
  • Julia に限らずPythonやRといった言語も活用できるようです.例えば ipywidgets のnotebook形式のドキュメント などもbinderを立ち上げて利用することができます.例えばhttps://github.com/jupyter-widgets/ipywidgets にある launch binder のアイコンをクリックすることでPythonの環境が立ち上がり,そこで動かすことができます.

基本的な使い方(利用する側として)

まず,どういうことができるのかを体感するために利用する立場としてBinderを触ってみましょう.

mybinder にアクセス

https://mybinder.org/ にアクセスします.下記の図のような画面で次の要素を指定します.

  • 動かしたいノートブックが置いてあるGitHubのリポジトリ
  • 対応するブランチ(基本masterで良い)
  • リポジトリを起点としたノートブックの置いてあるパスを指定(指定しなければリポジトリ全体をブラウザ上で見渡すことができる)

launch ボタンを押してしばらく待つと環境が立ち上がります.環境はDockerのコンテナが動くようです.動かしたいリポジトリが有名であれば誰かがイメージをビルドしているので(Binderが溜めている?)キャッシュを利用して環境が立ち上がります.個人開発者のこじんまりしているものであればイメージのビルドが走るログが流れるのでコーヒーを淹れながら待ちましょう.

image.png

変換できるリポジトリ

  • Configuration Files の項目を見るとリポジトリのルートにsetup.py, requirements.txt があれば Python の環境をBinderが用意するようです.Project.toml があればJuliaの環境を用意するようです.あとで紹介しますが,Dockerfile があればそのファイルをビルドするようです.

In the majority of cases, providing your own Dockerfile is not necessary as the base images provide core functionality, compact image sizes, and efficient builds. We recommend trying the other configuration files before deciding to use your own Dockerfile.

このようにリポジトリのルートにある設定ファイルを認識するようです.もし,リポジトリに binder というディレクトリがあれば Binder がBinder用の設定ファイルとして認識するようですね.これは開発する側から見ると共有に必要な設定を記述する設定ファイルと開発用の設定ファイルを区別するために役に立ちそうです.

参考: FAQ

Yes! Configuration files may be placed in the root of your repository or in a binder/ folder in the root of your repository (i.e. myproject/binder/). If a binder/ folder is used, Binder will only read configuration files from that location (i.e. myproject/binder/requirements.txt) and will ignore those in the repository’s root (myproject/environment.yml and myproject/requirements.txt).

  • もしリポジトリのメンテナーがBinderを知っている場合は launch binder というアイコンがリポジトリにあると思うのでそこをクリックすればOKです

基本的な使い方(開発・公開する側として)

  • 自分の作ったリポジトリを他の人に動かしてもらう手段として Binder を活用する方法を書きます.上でも書きましたように特に気張らなくても Binder がいい感じで認識するようなのでなんとなくトライするで済むかもしれません.
  • もっと込み入った環境,例えば,PackageCompilerXで重いパッケージのロードを軽くするようにしたJuliaのシステムイメージを使ってもらいたいとなるとなんも考えずにmybinder にアクセスしてよし何してもらうのは難しいでしょう.おそらくそれを実現するにはDockerfileを書くことになります.
  • ここではDockerfileによってカスタマイズした環境をBinderに持っていく方法を紹介します.ここでは開発・公開する側はDockerfileの作り方,コンテナ操作などは既知と仮定して話を進めます.手元にDockerfileがあってそれを使うと手元の環境では公開する対象の一通りの動作は確認できるんだけれど,それをどうBinderに認識させるのかがわからない人向けです.

ドキュメントを読む

  • 実は Use a Dockerfile for your Binder repository に全てが書いてあります.まずはこちらを読むことをお勧めします.
  • Binderの使用上コンテナ内部でrootユーザーになっているようなものは受け付けないようですので uid is 1000 となるユーザーを作ることになります.ドキュメントにもあるように
ARG NB_USER=jovyan
ARG NB_UID=1000
ENV USER ${NB_USER}
ENV NB_UID ${NB_UID}
ENV HOME /home/${NB_USER}

RUN adduser --disabled-password \
    --gecos "Default user" \
    --uid ${NB_UID} \
    ${NB_USER}

を追記しておきます.jovyan はBinderを動かしている際のユーザー名になるようです.手元で動かすときは -v, --volume オプションで必要なディレクトリをマウントしてると思いますが,Binderで動かしておくには必要な成果物を COPY でイメージの中に入れておくことになります.パーミッションの解決のために chown コマンドでリポジトリの所有者を解決しています.これも Binderのドキュメントに書いてある通りです.

# Make sure the contents of our repo are in ${HOME}
COPY . ${HOME}
USER root
RUN chown -R ${NB_UID} ${HOME}
USER ${NB_USER}

さて,Exampleは?

  • 拙著の MyWorkflow.jl をご覧ください.Dockerfile はこちら.特徴は下記の通り

    • PackageCompilerX.jl でパッケージをビルドする
    • jupytext で ipynb ではない形式のテキストをJupyterNotebookのフォーマットに自動で変換するようにしている.
    • これでバージョン管理をしやすくしている
    • 必要なパッケージを導入している
  • Binder対応のためユーザーをrootと設定してたのでBinderドキュメントの通りにユーザーを追加するにくわえています.

引っかかったところ

  • PackageCompierX.jl を使ったビルドの操作がルート権限じゃないとビルドできなくて
  • 一方でビルドは通るが一般ユーザー(jovyan) から使おうとすると実行できない.ひとまず所有権を一般ユーザーにすると使えるようになりました.
# Do Ahead of Time Compilation using PackageCompilerX
# For some technical reason, we switch default user to root then we switch back again
USER root
RUN julia --trace-compile="traced.jl" -e 'using OhMyREPL, Revise, Plots, PyCall, DataFrames' && \
    julia -e 'using PackageCompilerX; \
              PackageCompilerX.create_sysimage([:OhMyREPL, :Revise, :Plots, :GR, :PyCall, :DataFrames]; precompile_statements_file="traced.jl", replace_default=true) \
             ' && \
    rm traced.jl
# Make NB_USER Occupy julia binary
RUN chown -R ${NB_UID} /usr/local/julia
# Swich user again to NB_USER
USER ${NB_USER}

多分,一般ユーザーとしてjuliaのバイナリーをインストールすると行けるんだと思いまあすが,ベースイメージが julia:1.3.1 を使ってるので上の方法を採用しています.
- あとは jupytext が .jlipynb と認識してくれなかったので c.NotebookApp.contents_manager_class = 'jupytext.TextFileContentsManager'jupyter_notebook_config.py に追記することで解決しました.jupytext のリポジトリ には書いてあるのですがルート権限だとなくてもできていたのでハマりました.

RUN jupyter notebook --generate-config && \
    echo "\
c.ContentsManager.default_jupytext_formats = 'ipynb,jl'\n\
c.NotebookApp.contents_manager_class = 'jupytext.TextFileContentsManager'\n\
c.NotebookApp.open_browser = False\n\
" >> ${HOME}/.jupyter/jupyter_notebook_config.py

Binder用に変換した結果

Binder <- をクリックするとみられます.初回のビルドには結構時間がかかりますね.

Binder の良いところ

  • Jupyter Notebook が動くのは多くありますが, Interact.jl, ipywidgets のコンポーネントが動作するのが魅力的です.しかも無料で使うことができます.
  • 似たような仕組みとして Google のコラボラトリー がありますが, ipywidgets が動かない制限があるはずです.

例えばこういうことができます.

image.png

まとめ

Binderで成果物を共有する方法を書きました.Julia,Python, Rに限らず,Jupyter Notebook で動作する言語であれば同様にできると思うので皆さんトライしてみてください.

38
26
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
38
26