Jupyter Lab(Notebook)をローカル環境のDocker Composeで起動する方法

本記事では、ローカル環境でJupyter Notebookを使うために、Docker Composeを使ったJupyter Lab(Notebook)の環境を整備する方法を紹介しています。また、環境変数を渡す方法や、コンテナ間の通信方法についても紹介しています。

最近、ちょっとしたデータ処理のためにローカル環境でJupyter Notebookを使うことが増えてきました。自分やチームメイトが簡単に環境を準備できるように、Docker Composeを使ったJupyter Lab(Notebook)の環境を整備しました。本記事ではその内容を紹介します。

Dockerイメージ

Jupyterの公式から、Jupyter Docker StacksというDocker Imageのセットが公開されています。

用途に合わせて、いくつかのイメージが提供されています。

https://jupyter-docker-stacks.readthedocs.io/en/latest/using/selecting.html

jupyter/docker-stacks-foundationは他の全てのイメージのベースイメージとなっています。jupyter/base-notebookはベースイメージにNotebook、Jupyter Labなどを追加したイメージです。特別な計算処理が必要なければ、このイメージを使うのが良いと思います。その他、用途に応じて様々なイメージが用意されています。

また、自分でイメージをカスタマイズする方法は以下の記事で紹介されています。

Jupyter Docker Stacksのコンテナをカスタマイズする

設定

以下が、ローカル環境で使用するときのdocker-compose.ymlです。

version: '3.4'
services:
notebook:
image: jupyter/base-notebook:latest
command:
- start-notebook.sh
- --NotebookApp.token='' # 認証を無効化
- --NotebookApp.disable_check_xsrf=True # CSRFチェックを無効化
ports:
- 8888:8888
volumes:
- ./notebook:/home/jovyan/work

ローカル環境なのでセキュリティに関する機能をオフにしています。具体的には、認証を無効化しています。認証を無効化するとVSCode拡張などからのリクエストがCSRFチェックに引っかかるようになるので、CSRFチェックも無効化しています。

この他にも、Jupyterサーバーのコンフィグは、起動コマンドのstart-notebook.shを通じてJupyterサーバーに渡すことができます。

Notebookからローカルのデータセットなどにアクセスできるように、volumeをマウントしています。コンテナ側のデフォルトのワークスペースは/home/jovyan/workです。

環境変数

Notebookにシークレットなどの値を環境変数で渡したい場合があると思います。前提として、ローカル環境の環境変数は.envで管理しているとします。

簡単な方法としては、docker-compose.ymlに環境変数を書く方法があります。

services:
notebook:
environment:
- SECRET_KEY=${SECRET_KEY}

このようにすることで、Notebook側では、以下のように環境変数を参照することができます。

import os

os.environ.get("SECRET_KEY")

また、環境変数がすごく多くてdocker-compose.ymlに書くのが大変な場合には.envをNotebookで読み込む方法を取ることもできます。

まず、volumeをマウントして.envにアクセスできるようにします。そして以下のように.envを読み込みます。

%pip install -U python-dotenv
%load_ext dotenv
%dotenv -o

これでNotebookに.envの内容が読み込まれます。Pythonのコードで環境変数を参照する方法は、1つ目と同じです。

コンテナ間の通信

Notebookから、別のコンテナのサービスにアクセスしたい場合があります。このとき、同じdocker-compose.ymlで定義されたサービスであれば、サービス名でアクセスできます。

version: '3.4'
services:
notebook:
image: jupyter/base-notebook:latest
weaviate:
image: semitechnologies/weaviate:1.19.1

例えば、weaviateというサービスがある場合は、weaviateという名前でIPが解決できます。

import weaviate

client = weaviate.Client(
url = "http://weaviate:8080",
)

おわりに

Pythonの環境構築は慣れていないと躓くポイントが多いと思うので、少しでも簡単に環境をセットアップできるようにしたいと思いました。参考になれば幸いです。