Python on JupyterLab on Docker


皆さんは、Python 環境をどのように構築していますか?

ネットからダウンロードをしたものを使っている人、パッケージマネージャを使っている人、pyenv 等を使っている人など様々だと思います。
僕も環境構築が必要になるたびに、様々な方法で Python 環境を構築してきました。
しかし、職場、研究室、自宅などの PC にそれぞれ環境構築をしなければならいことにうんざりしていました。
更にコロナ禍ならではの事情もあります。職場や研究室で Python の環境をいい感じに整えていても、コロナの感染状況が悪くなれば急に自宅で作業しなければならなくなり、また環境を整える必要が出てきます。
さらに、前回の環境構築から時間がたっていると、どうするのが最適なのか思い出すのも面倒になります。(普段から使ってる C++ならスラスラと環境構築できますが、そうでない言語は色々忘れちゃってます。)

最近 Docker を使うことが多く、そのありがたさを日々感じる毎日なのでどうせなら Docker で環境を作ろうと思いたちました。
Docker であれば、一度環境構築用の Dockerfile や docker-compose.yml を用意すれば、他の PC で作業しなければならなくなっても同じ環境を docker run ... とか docker-compose up ですぐ作れてしまいます。
また、その環境を汚すことは無いので衛生的です。(衛生的とは w?)
デメリットとしてはルート権限にアクセス可能な環境でないと使えないことが挙げられます。

今回は JupyterLab を使いたかったので、JupyterLab 環境を Docker で作った備忘録を書いていきます。

必要な環境

  • Linux コンテナを動かすことができる環境

ベースとなる Docker イメージなど

今回は JupyterLab 公式のイメージを利用しました。JupyterLab は公式でいくつかのイメージを用意しています。
最小構成のものから、様々なライブラリを含んだものまで多くの種類があります。下記のページからどのようなイメージが用意されているか確認することができます。

https://hub.docker.com/u/jupyter

今回はストレージに余裕がある環境を使用したので、将来性も考えてdatascience-notebook というイメージを選択しました。
このイメージは NumPy や SciPy などの数値計算ライブラリが入っていたり、R や Julia も入っていたりします。
通常であればこれらのものは一つずつコマンドを打ってインストールしなければいけませんが、今回は Docker を使うのでこれらがコマンド一つで入ってくれます。
便利ですね!

また機械学習用のライブラリもあると便利です。僕はあまり深層学習のプログラムを書きませんが、たまに PyTorch を使うので今回は PyTorch も使えるような環境を作りました。

Dockerfile

今回は Docker や Docker Compose についてある程度わかっていることを前提に話を進めていきます。
もし Docker についてよくわからない場合は以下のサイトなどを参考にすると良いでしょう。

https://knowledge.sakura.ad.jp/13265/
https://knowledge.sakura.ad.jp/21387/

まずDockerfileを記述していきます。 公式のdatascience-notebookイメージのままでも十分利用できますが、先程書いたとおり PyTorch を導入したいのでDockerfileを作成して追加します。
他にも、Vim のバインドを使えるようにしたりフォーマッタを導入したりしたいので、それらのインストールの処理を書いていきます。

# datascience-notebook をベースとして利用
FROM jupyter/datascience-notebook:latest

RUN jupyter labextension install @axlair/jupyterlab_vim \
    && conda install -c conda-forge jupyterlab_code_formatter \
    && jupyter serverextension enable --py jupyterlab_code_formatter \
    && conda install black  isort -y \
    && pip install torch torchvision \
    && conda clean --all \
    && rm -rf /home/jovyan/.cache/*

のようにします。

RUNで行っているコマンドについての説明です。

  • jupyter labextension install @axlair/jupyterlab_vim
    • Vim 用の拡張をインストール
  • jupyter labextension install @axlair/jupyterlab_vimjupyter serverextension enable --py jupyterlab_code_formatter
    • フォーマッタのための拡張をインストール
  • conda install black isort -y
    • Python のフォーマッタの black とモジュールをソートしてくれる isort をインストール
  • pip install torch torchvision
    • PyTorch のインストール
  • conda clean --allrm -rf /home/jovyan/.cache/*
    • キャッシュを削除(イメージサイズを減らすため)

docker-compose.yml

続いて、docker-compose.ymlを記述します。今回利用するコンテナは1つなので、Docker Compose を使う必要性はそこまで大きくはありませんが、ポートの設定などを書けるのでdocker-compose.ymlも利用します。
docker-compose.ymlDockerfile と同じディレクトリに配置して下さい。

version: "3.8"
services:
  jupyterlab:
    build:
      context: .
      dockerfile: Dockerfile # イメージのビルドに用いるDockerfile
    image: myjupyterlab # 作成するイメージの名前
    container_name: jupyterlab # 起動時のコンテナの名前
    environment: # 環境変数の設定
      TZ: Asia/Tokyo # タイムゾーン
      JUPYTER_ENABLE_LAB: "yes" # コンテナ起動時にJupyterLabを起動する
    volumes:
      - /path/to/your/workspace:/home/jovyan/work # 作業ディレクトリをDockerから参照できるようにする
    ports:
      - 8888:8888 # ホストの8888ポートをコンテナの8888ポートとして使う
    restart: always # 再起動時に起動する
    deploy: # GPU用の設定(NVIDA GPUの利用者用, NVIDIA container toolkitの導入が前提)
      resources:
        reservations:
          devices:
            - driver: nvidia
              capabilities: [utility, compute, video]

上記のように書いて下さい。説明はコメントに書きました。
volumes は適宜作業ディレクトリを設定して下さい。

イメージのビルド

Dockerfiledocker-compose.yml があるディレクトリで、

docker-compose build

とすると、イメージビルドが始まります。この処理は Dockerfile を書き換えない限り(そして作成したイメージを削除しない限り)最初の1度のみで良いです。

コンテナの起動 & URL および token の確認

docker-compose up -d

と打つとコンテナが起動します。
-d オプションをつけたのでログ等を見ることができません。

docker logs (コンテナ名)

とすることで、token 付きの URL を知ることができます。コンテナ名は docker-compose.ymlcontainer_name で設定したものにして下さい。
docker ps コマンドで確認することもできます。
token 付きの URL をブラウザを開いたら、JupyterLab が起動しているのを確認できるはずです。 Python のノートブックを開くと Vim のバインドが使えたり、上にあるボタンでフォーマットができるようになっていることも確認できると思います。

終了

終了したい場合は

docker-compose down

と打って下さい。

まとめ

今回は Docker を用いて Python+JupyterLab の環境を作りました。
今まで Docker をあまり使ってきませんでしたが、今回その良さを十分に感じることができました。
Docker の良さの一つは自分が詳しくない言語などの開発環境を、他の人が作ったイメージを組み合わせることで簡単に構築できることだと思います。
これからも積極的に Docker を使っていきたいと思います。