Chromebook環境でPythonの実験用にJupyter Notebookを使い、その使いやすさに感心して、Windows上にも環境を構築したくなりました。
とはいえほかの環境を汚してしまいたくないので、DockerでJupyter Notebookのコンテナを作り、その中に実験環境を構築することに。
ついでにインストールしたモジュールの履歴や、ファイルをWindows PC上と同期できるようにし、コンテナを落としてもファイルが消えない(永続化)できるようにしました。
環境
- Windows 10 Home(10.0.18362)
下準備
Dockerのインストールを行います(直前にPCをリフレッシュしていたのでおさらいも兼ねて)。ChocolateyにDocker-Toolboxが入っているのでここからインストールすると非常に楽です。
choco install -y docker-toolbox
インストールが終了したら、VirtualBoxの設定画面から、Windows上のどこかのフォルダを「/share」という名前で共有フォルダに設定します。
docker-compose.ymlを作成する
最近はDockerfileを直接作らず、docker-compose.ymlというファイルを作り、docker-composeコマンドでコンテナを構築するのが流行っている(?)そうです。
これを使うとポートの開放やホストOSとの共有フォルダ設定など、dockerコマンドのオプションで指定していたことの一部をまとめることができるので、非常に楽です。
version: "3.7"
services:
notebook:
image: jupyter/base-notebook
ports:
- target: 8888
published: 8888
protocol: tcp
mode: host
volumes:
- type: bind
source: /share/data
target: /home/jovyan/work
- type: bind
source: /share/pipenv
target: /home/jovyan/.local
起動スクリプトを書く
docker-composeは多くのコマンドライン処理をまとめることができますが、かといって起動用のバッチが不要になるわけではありません。
今回はコンテナで起動したJupyter Notebookをブラウザで開く処理も追加します。
docker-compose run -d --service-ports notebook
Sleep 1
if ((docker-machine ssh default docker ps) -join "\n" -match "jupyter_notebook[\w\d_]+") {
$cid = $Matches[0]
if ((docker-machine ssh default docker exec $cid jupyter notebook list) -join "\n" -match "\?token=(\w+)") {
$ip = docker-machine ip
$token = $Matches[1]
start ("http://{0}:8888/?token={1}" -f $ip, $token)
}else {
echo "Notebook Open Failed"
}
}else {
echo "Container Boot Failed"
}
これらを同一のフォルダに配置し、DockerのホストOSが起動している状態でps1ファイルを実行すれば、Jupyter Notebookがブラウザで起動します。
ホストOSやコンテナを落としても消えてほしくないデータはworkディレクトリ配下に、pipコマンドでモジュールをインストールする際は、オプションに–userをつけることをお忘れ無く。
その他解説
docker-compose.ymlの各種コマンドの解説
image
jupyterで公開されているDockerイメージを参照します。
今回はあくまでただの実験用なので、base-notebookを使います。
用途ごとにイメージは変わるので、以下参考サイトより自分の用途に合ったコンテナを探してください
ports
dockerコマンドで言う-p 8888:8888と同等の処理です。
8888ポートを開放します。
volumes: /share/data
~/workディレクトリを、ホストOS上の/share/dataディレクトリと結びつけます。
VirtualBox自身の共有設定により、このフォルダはWindowsのフォルダと同期されます。
volumes: /share/pipenv
~/.local/はpipコマンドに、オプション–userを指定したときのモジュールのインストール先です。
このディレクトリをWindowsと共有しておくことで、モジュールのインストール状況が永続化されます。
PowerShellスクリプト内の処理の解説
docker-compose run -d –service-ports notebook
コンテナを実行します。
なお、docker-composeコマンドを使った場合、オプションに–service-portsを入れないと、ポートが外部に開放されないようですので注意。
docker-machine ssh default…
ホストOSのコマンドより、起動したDockerコンテナのIDを探します(戻り値は改行区切りのリストですので、かならず-joinコマンドでテキストに変換してください)。
コンテナの名前は、[docker-compose.ymlがあるフォルダの名前]_[yml内に書いたサービスの名前]_通番になるとのことです。
docker-machine ssh default docker exec…
起動しているJupyter Notebookより、トークンIDを取得します。
docker-machine ipでIPアドレスを取得すれば、コンテナ内のJupyter NotebookにアクセスするためのURLが生成できますね。
参考ページ
-
- pip でインストール先を指定する方法 – ためすう
-
- Docker Compose – docker-compose.yml リファレンス – Qiita
-
- JupyterのDockerイメージまとめ – Qiita
-
- docker-composeを使うと複数コンテナの管理が便利に – Qiita
- docker-compose run は portをmappingしない – フリーランチ食べたい
今回作成したファイル
- TakamiChie/docker-jupyter-env: DockerコンテナのJupyter実験環境
感想
-
- ホストOSに接続せずにdocker-composeコマンドなどだけでDockerがいじれるようになったのは非常に楽だし、今回のようなバッチファイルが作りやすくて助かる
複数コンテナの同時起動などもできるようなので、基本的にはdocker-composeを使えばよさげ(オプションでDockerfileを指定して、コンテナごとに細かなカスタマイズを施すことも可能とのこと)
–service-portsをつけないとサービスが公開できないのは割と罠っぽいし、けっこう抜けている記事も多いので要注意。ここが一番詰まった
Chocolatey最高。