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=''
image.png
{
    "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が導入できない

を参照してくださいい。

广告
将在 10 秒后关闭
bannerAds