jupyter/scipy-notebookや、jupyter/datascience-notebookなど、JupyterをDockerで使える(Jupyter Docker Stacks)についてまとめてみます。
このdockerイメージは、例えば普段使っているPCはWindowsやMacだけど、Linuxでしか動かないモジュールを使いたい人や、データ分析のタスクで、本番環境と開発環境を同じにしつつJupyterで開発したい人などはよく使っていると思います。ただこのdockerイメージは少し癖が強くデフォルトの状態で起動するとapt-get
すらできないとか使い方がよくわからない部分があると思います。そこでこの記事で個人的にTipsをまとめてみました。
また私が使っているDocker + VSCode + Remote Containerのリポジトリもアップします。
SolKul/vscode-jupyter-container2
既にJupyteのDocker(Jupyter Docker Stacks)についての記事やサイトは山程出ています。まずそれらについてまとめ、そこにかかれていない私が役に立つと思うポイントをその後にまとめようと思います。
2022/6更新
デフォルトのサーバーバックエンドがjupyter serverに切り替わった問題に対処
JupyterのDockerについての過去の記事や参考サイト
Dockerで基本的なData Science環境(Jupyter, Python, R, Julia, 定番ライブラリ)を構築する。
この記事でパスワードの設定や、ポートフォワーディング、ボリュームの共有など基本的なことはすべて抑えられると思います。ただ、この記事はコンテナの起動をコマンドラインで行っています。dockerの知識がないうちはこれでdockerに慣れるのもいいですが、毎回この長いコマンドを打つのも大変です。慣れてきたらDockerfile
+docker-compose
を使ったほうが効率的です。
Docker + VSCode + Remote Containerで作る快適Jupyter Lab(Python)分析環境
この記事はVS CodeのRemote Containerでコンテナを動かしています。VS Codeであればファイルの配置もグラフィカルに表示され楽ですし、ファイルの中身もテキストエディタで編集できます。docker-compose
も使っているので毎回コマンドを打つ必要がないです。何よりもVS Codeの強力なデバック機能や拡張機能が使えるのは魅力的です。
Jupyter Docker Stacksについてメモ
以下、Jupyter Docker Stacksを使う際のTipsをまとめます。
docker run
よりdocker-compose
を使う
dockerに慣れてきたらdocker-compose
を使うほうが断然楽です。次のdocker run
コマンドと、その下のdocker-compose.yml
は同じ働きをします。
docker run \
--user root \
-e GRANT_SUDO=yes \
-e TZ=Asia/Tokyo \
-p 8888:8888 \
--name notebook \
-v ./work:/home/jovyan/work \
jupyter/datascience-notebook \
start-notebook.sh \
--NotebookApp.password='sha1:YOUR_PASSWORD_HASH_VALUE'
version: '3'
services:
notebook:
image: jupyter/datascience-notebook
user: root
ports:
- '8888:8888'
environment:
- GRANT_SUDO=yes
- TZ=Asia/Tokyo
volumes:
- ./work:/home/jovyan/work
command: start-notebook.sh --NotebookApp.password='sha1:YOUR_PASSWORD_HASH_VALUE'
コマンドだと間違ってEnterを押してしまった時点で起動してしまいますが、docker-compose.yml
であれば落ち着いて編集し、設定が正しいか確認したうえでコンテナを立ち上げることができます。
まず、次のコマンドで、docker-compose.yml
の設定が正しいか検証でき、また(上記のdocker-compose.yml
ではホスト環境変数は使っていませんが)設定したホスト環境変数に正しく値が代入されるかをチェックすることができます。
# docker-compose config
そして立ち上げる場合はdocker-compose up
とすればいいだけです。
docker run
のどのオプションがdocker-compose.yml
のどの項目に対応しているかなどは
複数のDockerコンテナを自動で立ち上げる構成管理ツール「Docker Compose」(Dockerの最新機能を使ってみよう:第7回)
などを参照してください。
また、docker run
コマンド-e
オプションや、docker-compose.yml
のenvironment
でコンテナ中に環境変数を設定しています。
docker run
の-e
オプションについては公式リファレンスを参照してください。
run — Docker-docs-ja 19.03 ドキュメント
docker-compose
の環境変数についても公式リファレンスを参照するか、私が過去まとめた記事があるのでそちらを参照してください。
docker-composeのenv_fileと.envファイルの違い
また、.env
ファイルを追加し、docker-compose.yml
を適切に書き換えればプロキシ下などでも使えます。詳しくはdocker-composeでのプロキシ設定を一つのファイルにまとめるを参考にしてください。
VSCode+Remote Containerで使う
さらに言えば、VSCode+Remote Containerで使えば更に快適になります。上で述べたように、VSCodeであれば使うファイルの配置もグラフィカルに表示されるので、例えば、分析対象のデータを配置するときもわかりやすいです。ファイルの中身もテキストエディタで編集できます。ポートフォワーディングも後からできます。docker-compose.yml
も使っているので毎回コマンドを打つ必要がないです。何よりもVSCodeの強力なデバック機能や拡張機能が使えるのは魅力的です。なんならipynbファイルもそのまま開けます。
私がVSCode+Remote Containerで使う場合の例をSolKul/vscode-jupyter-container2にアップしました。
VSCodeをインストールし、拡張機能のRemote Containersをインストールしてください。そしてVSCodeで適当なフォルダを開いて、このリポジトリをチェックアウトしCtrl+Shift+pでコマンドパレットを開き、「Remote-Containers: rebuild and Reopen in Container」を検索してEnterを押すことで、VSCodeがdocker-compose.yml
を参照してコンテナを立ち上げ、中に入ってくれます。
このリポジトリのファイル構造と各ファイルは次のようになります。
/
├ .devcontainer/
│ ├ .env
│ ├ devcontainer.json
│ ├ docker-compose.yml
│ └ Dockerfile
└ work/ ※1
version: '3.3'
services:
jupyter_dev: # jupyterコンテナのサービス名※2
build: . # ビルド対象のDockerfileが同じフォルダ内にあるためピリオド(.)を打つ
environment:
- GRANT_SUDO=yes
- DOCKER_STACKS_JUPYTER_CMD=notebook
working_dir: /home/jovyan/work
user: root
volumes: # ホストとのボリューム共有。../workは上のフォルダ構造で示した※1の一つ上の階層のworkフォルダを指し示す。
- type: bind
source: ../work
target: /home/jovyan/work
command: start-notebook.sh --NotebookApp.token=''
ポートフォワーディング下のようにVSCode上で後からできるのdocker-compose.yml
にはポートフォワーディングの設定は書いてません。
{
"name": "jupyter-devcontainer-project",
"dockerComposeFile": [
"./docker-compose.yml"
],
"service": "jupyter_dev", //サービス名はdocker-compose.yml内のサービス名※2と一致させる
"extensions": [
"ms-python.python"
],
"workspaceFolder": "/home/jovyan/work"
}
# pandas、numpy、scipy、 scikit-image、matplotlibなど一通り入っているjupyter/scipy-notebookを使う。
# また、常にpullするimageを固定したいので、一意のtagをつける。
FROM jupyter/scipy-notebook:44fe185f9495
USER jovyan
RUN conda install -y jupyter_contrib_nbextensions
VSCode+Remote Containerの詳しい使い方については「VSCode Remote Container」と検索するか、公式リファレンス(英語)を参考にしてください
bashを起動したい場合
新しいモジュールをインストールしたり、ファイル操作やapt-get
などbashを操作したい場合があると思います。その場合はdocker ps
でコンテナIDを調べ、
docker exec -it コンテナID /bin/bash
などすれば、bashを起動できます。またはVScodeでRemote containerしている場合は新しくターミナルを開けばいいです。
docker ps
やdocker exec
などのコマンドがわからない場合は
Docker ハンズオン - 基本コマンド編
などを参照してください。
ただ、デフォルトで使っている場合、ユーザーはjovyanになり、権限がないのでapt-get update
やapt-get install
はできないです。これについては次で述べます。
ユーザーと権限について
ユーザーは管理者であるrootと、jupyter notebookを実行するjovyanがいます。ブラウザでアクセスでき、ファイルを編集できるjupyter notebookを管理者権限で実行するのはセキュリティ的にまずいので、jupyter notebookはjovyanで起動するようになっています。
デフォルトではユーザーはjovyanになります。なのでデフォルトの状態で
docker exec -it コンテナID /bin/bash
とbashを実行しても、ユーザーはjovyanとなり、権限がないのでapt-get update
やapt-get install
はできません。
しかしdocker exec
コマンドの--user
オプションを使えばrootでbashを起動できます。
https://docs.docker.jp/engine/reference/commandline/exec.html
docker exec -it --user root コンテナID /bin/bash
これでapt-get
などが使えるようになります。
また、Dockerfile
中で最後の行で以下を追加する、
USER root
もしくは、docker-compose.yml
で
user: root
とコンテナ起動ユーザーをrootに切り替えた場合、デフォルトでbashを開くとユーザーはrootで起動し、同じくapt-get
などが使えるようになります。先程のdocker exec
コマンドの--user
オプションを使う場合と比べて、Dockerfile
やdocker-compose.yml
でrootで設定した場合、VSCodeでRemote Containerで開発している場合に、VSCode上でTerminal>New Terminal
で新しいターミナルを起動した際に、rootでbashが起動するようになるので、VSCodeを使っている場合はこちらのほうが便利です。また、コンテナ起動ユーザーをrootにしても、jupyter notebookはjovyanで起動するので安心してください。
rootユーザーから、su jovyan
でjovyanに切り替えることができますが、このjovyanでは/opt/conda/bin/
のパスが通っていないため、pip
コマンドやconda
コマンドが使えまえん。export PATH=$PATH:/opt/conda/bin
などとして、環境変数のPATH
に/opt/conda/bin/
を加えれば、pip
コマンドやconda
コマンドが使えるようになります。
また、同じくコンテナ起動ユーザーをrootに切り替えた上で、環境変数GRANT_SUDO
にyes
を指定、つまりdocker-compose.yml
で、
environment:
- GRANT_SUDO=yes
としていれば、su jovyan
としjovyanに切り替えた後のjovyanはsudo
が使えるようになり、sudo apt-get
などができます。
つまりGRANT_SUDO=yes
でかつコンテナ起動ユーザーがrootならjovyanはsudo
を使えるということです。詳しくは、
を参照してください。
起動時のコマンドについて
jupyter/datascience-notebookなど Jupyter Docker StacksのDockerコンテナは立ち上がると同時にデフォルトでstart-notebook.sh
が走り、各種設定を行います。(GRAT_SUDO
の有効化など)。start-notebook.sh
が必要な設定を行うので、Dockerfile
のCMD
コマンドやdocker-compose
のcommand
設定で、起動時のコマンドをstart-notebook.sh
以外のコマンドを変更するのは避けたほうがいいです。
また、GRAT_SUDO
の有効化やjovyanのユーザーID、グループIDの変更などstart-notebook.sh
が行ういくつかの設定はコンテナ起動ユーザーがrootでないと有効になりません。
詳しくは以下のページなどを参照してください。
Common Features — Docker Stacks documentation
Jupyter notebookを使うための設定
Jupyter Docker Stacksは2022年1月ごろ、デフォルトのサーバーバックエンドをjupyter notebookからjupyter serverに切り替えました。これに伴いデフォルトのエディタがjupyter notebookからjupyter Labに切り替わりました。
バックエンドがjupyter serverのままでも、jupyter notebookは引き続き使えます。loacalhost:8888
にアクセスすると、jupyter lab
に、loacalhost:8888/tree
にアクセスすると、従来のjupyter notebook
にアクセスします。
しかし、様々な拡張機能があるjupyter_contrib_nbextensionsはjupyter notebookでしか使えず、しかもバックエンドがjupyter serverだと/tree
のnotebookからもnbextensionは使えなくなってしまいます。私は選択中の文字を強調するHighlit Selected Word
を使いたいため、jupyter notebook+jupyter_contrib_nbextensionsを使い続けています。いまのところ同じ機能はjupyter labは対応していないようです。
なのでバックエンドをjupyter notebookに切り替える必要があります。
Common Features — Docker Stacks documentationによるとコンテナ内の環境変数DOCKER_STACKS_JUPYTER_CMD
をnotebook
に設定することで、立ち上がったサーバのバックエンドjupyter notebookに切り替えることができます。なので、docker-compose.yml
中で次のように設定しています。
environment:
- DOCKER_STACKS_JUPYTER_CMD=notebook
モジュールのインストールとユーザー権限について
rootでconda install
などでモジュールを管理者権限でインストールしてしまうと、jupyter notebookを実行するjovyanユーザーで不具合が起きるように思えますが、使っていて、conda install
やpip install
などモジュールのインストールをrootとjovyanどちらのユーザーで実行しても、ほぼほぼ、Pythonのプログラミングには問題ないように感じます。
ただ、git clone
などファイル、フォルダを生成する場合は、jovyanで行ったほうがいいです。
rootで
root $ git clone リポジトリ
としてしまうと、クローンしたリポジトリのファイル、フォルダの書き込み権限がroot権限になってしまいまい、その後不具合を起こす可能性があります。こうしてしまった場合は、chown
で所有者を書き換えましょう。
また、jupyter_contrib_nbextensions
のインストールもjovyanで行ったほうがいいです。
git clone
と同様にrootで
root $ conda install -y jupyter_contrib_nbextensions
としてしまうと、nbextensions
関連のファイルがroot権限になってしまいます。jupyter
上にnbextensionsのタブが現れはしますが、jupyter
起動ユーザーがjovyanなため、その状態でどのエクステンションを有効にしても実際は権限の問題で/home/jovyan/.jupyter/nbconfig/
以下に存在する設定ファイルが書き換わらずに、F5で更新すると無効になってしまいます。
なので、jupyter_contrib_nbextensions
のインストールは次のようにDockerfile
内でjovyanユーザーで予めやっておいたほうがいいです。
USER jovyan
RUN conda install -y jupyter_contrib_nbextensions
詳しくは
jupyter notebookが使えるdockerにnbextensionsが導入できない
を参照してくださいい。