dockerによるkerasとtensorflow, jupyter labの環境構築およびport forwardingでのjupyterへの接続


概要

dockerによってkerasのgpuおよびjupyterlab環境構築をする。
dockerがどういうものか、dockerのインストール等は省略する。
またついでにport forwardingについて軽く解説する。

イメージのpull

tensorflowのdockerhubにてタグがlatest gpuのimageをpullする。
タグがlatestのみだとcudaが使えない。
やることは以下の通り

$ sudo docker pull tensorflow/tensorflow:latest-gpu

イメージの確認

$ sudo docker images
REPOSITORY                        TAG                 IMAGE ID            CREATED             SIZE
tensorflow/tensorflow             latest-gpu          20fd065e3887        7 weeks ago         3.15GB

必要そうなモジュールとjupyterをインストール

インストールするモジュール

今回importするのは

  • matplotlib
  • cv2 (opencv-python)
  • keras
  • jupyter lab

インポートする前にdockerのコンテナをイメージから作成しておく。環境構築の際はrootで入る。

$ sudo docker run -it tensorflow/tensorflow:latest-gpu

pipとaptのアップデート

# pip install --upgrade pip
# apt-get update -y

opencvのインストールのための準備

以下を参照した
DockerでpythonのTensorFlowとOpenCVの実行環境を構築する

# apt-get install -y libopencv-dev

結構時間がかかる。

必要モジュールのインストール

# pip install matplotlib opencv-python keras
# pip install jupyterlab

モジュールがimportできるかテスト

# python
Python 3.6.9 (default, Jul 17 2020, 12:50:27)
[GCC 8.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import matplotlib
>>> import numpy
>>> import cv2
>>> import keras
2020-09-20 01:02:34.313977: I tensorflow/stream_executor/platform/default/dso_loader.cc:48] Successfully opened dynamic library libcudart.so.10.1
>>> import tensorflow

大丈夫そうだ。
Ctrl + dで対話モードを抜けられる。
jupyterlabもこれにてインストールできているのだが、実行するためにはport forwardingをしないといけない。詳しい実行手順を確かめたかったら最後までこの記事を読んでほしい。

イメージのコミット

jupyter lab のテストの前に一旦コンテナをイメージにcommitする。つまり色々インストールした現在の状況をセーブする。
Ctrl+p,Ctrl+qでコンテナを稼働させたままコンテナから抜ける。

現在稼働中のコンテナの確認

$ sudo docker ps -n=-1
CONTAINER ID        IMAGE                              COMMAND                  CREATED             STATUS              PORTS                  NAMES
a24503258ede        tensorflow/tensorflow:latest-gpu   "/bin/bash"              24 minutes ago      Up 24 minutes                              romantic_gauss

コンテナのコミット

$ sudo docker commit a24503258ede keras-jupyter

sudo docker commit (コンテナID) (つけたいイメージの名前) のようにする。以降今まで作ったものはkeras-jupyterという名前のイメージをビルドすれば先程のコンテナが出来上がる。

コンテナの停止

先程のコンテナを一旦止める。

$ sudo docker stop a245
$ sudo docker ps -n=-1
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                  NAMES

コンテナIDは最初4文字くらいで反応してくれる。

port forwardingについて

これからjupyterlabの動作確認を行うのだが、ついでにport forwardingについて軽く説明する。

port forwarding(ポートフォワーディング)とは

現在私は以下の図のように私自身のパソコンからサーバにssh接続し、その上でdockerを走らせて、更にその上でjupyterlabを起動させようとしている。
しかしjupyterlabはブラウザ上で扱うもののためssh接続とは別にもう一つjupyterlabまでの接続経路を作成しないといけない。

そのためブラウザ上でもjupyterに接続できるようssh以外の接続経路(トンネル)を作成することをport forwardingという。
以下の図のように各コマンドにオプションを加えることでsshのポート22番の他にトンネルを開けることができる。

ただ今回は解説のためにすべてポート番号を変えているが、間違えないようすべてのポートフォワードするポートは8888などに統一すると良いだろう。
それでは具体的にjupyterlabのテストを通してポートフォアディングができているか確認していこう。

jupyterlabへのport forwarding

sshでのport forward

まずローカルからsshでサーバに接続する。

$ ssh [email protected] -L 8800:x.x.x.x:8880

-L {ローカルのポート番号}:{サーバのip}:{サーバでつなぎたいポート番号} のようにオプションを付ける。

dockerでのport forward

-p 8880:8888をオプションに追加する。
これによりサーバからdockerにアクセスした際にサーバのポート8880番がdockerの8888番につながる。

$ sudo docker run -it -p 8880:8888 keras-jupyter

これによりローカルの8800番はdockerの8888番につながった。

jupyterlabの起動

次にコンテナ上でjupyterlabを以下のコマンドで起動する。

# jupyter lab --port 8888 --ip=* --allow-root

以下コマンドの解説

  • まずdockerのport8888番がローカルとつながっているためjupyterのportを8888とする。(--port 8888)
  • jupyterをそのまま起動するとipがわからず接続できないためdocker環境とアドホックにつなぐ。(--ip=*)
  • 最後に現在dockerはrootで起動してるためルートでの接続を許可する。(--allow-root)

以下のような出力のhttp://127.0.0.1:8888/?token=614f6e5d410a1c459baa691ee28fdd0e2593c4644189a09e`をコピー。


[W 02:52:43.023 LabApp] WARNING: The notebook server is listening on all IP addresses and not using encryption. This is not recommended.
[I 02:52:43.028 LabApp] JupyterLab extension loaded from /usr/local/lib/python3.6/dist-packages/jupyterlab
[I 02:52:43.028 LabApp] JupyterLab application directory is /usr/local/share/jupyter/lab
[I 02:52:43.030 LabApp] Serving notebooks from local directory: /
[I 02:52:43.030 LabApp] Jupyter Notebook 6.1.4 is running at:
[I 02:52:43.030 LabApp] http://0829a84d25eb:8888/?token=614f6e5d410a1c459baa691ee28fdd0e2593c4644189a09e
[I 02:52:43.030 LabApp]  or http://127.0.0.1:8888/?token=614f6e5d410a1c459baa691ee28fdd0e2593c4644189a09e
[I 02:52:43.030 LabApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).

jupyterへの接続

先程のurlの一部を以下のように変更し、ローカルのブラウザに貼り付ける。

http://localhost:8800/?token=614f6e5d410a1c459baa691ee28fdd0e2593c4644189a09e

これでサーバで実行中のjupyterにポートフォアディングによって接続できる。

余談

実際dockerを実行する際にはユーザーをdockerとserverでバインドするなどここでは詳しく解説しないが以下のようにdocker run コマンドをaliasに登録して使うとよいだろう。


alias docker-run-keras = 'sudo docker run -v /etc/group:/etc/group:ro -v /etc/passwd:/etc/passwd:ro -v $HOME:$HOME -u $(id -u $USER):$(id -g $USER) -it --gpus 2 -p 8888:8888 --shm-size 30g keras-jupyter