Dockerでデータ分析環境を手軽に作る方法
何かデータ分析を行わなければいけないとき、手軽に分析環境を用意したいというニーズがあります。
Jupyter Notebook上でnumpy、pandas、matplotlib、scikit-learnあたりが使えれば十分でしょうか。XGBoostやLightGBMといったライブラリも使えるようにしておきたいという人もいるかと思います。
一方、ローカルにいろいろなライブラリをインストールしていくと、次第に環境が汚れていってライブラリの衝突などが起こりやすくなってしまいます。
KaggleにはKernelという計算環境があり、そこには主要な機械学習ライブラリが予めインストールされています。データ分析をやっていく上で不自由はありません。今回はDockerとdocker-composeを使ってKaggle Kernelを手元に再現し、ポータブルな分析環境として使う方法を紹介します。
データ分析界隈には、なんとなくDockerを敬遠しているような人もいるかと思いますので、この機会に入門してしまいましょう。
解説はMacOSで行いますが、Dockerとdocker-composeがインストールできれば同じ方法が使えるかと思います。
登場する用語の説明
Dockerは、まっさらな環境を簡単に作るツールです。
Dockerfileというファイルに環境の設定を書けば、そのとおりの環境を作ることができます。他人が作ったDockerfileに自分なりのカスタマイズを加えることも可能です。
今回は、Kaggle公式が公開しているpython環境をもとにカスタマイズを行っていきます。
加えてコンテナ(container)とイメージ(image)という用語も覚えましょう。
イメージはDockerfileをビルドして作ります。イメージはDockerfileという設計図を元に作られた「型」だと考えて良いと思います。
イメージを元にコンテナを起動し、そのコンテナ上でJupyterを立ち上げます。利用する際はコンテナにアクセスします。イメージができていればコンテナは数秒で起動できますし、どれだけ環境を汚してもイメージから起動しなおせばまた使うことができます。同じイメージから何個もコンテナを起動することも可能です。
Google Container Registryは便利なイメージが多く登録されているサイトです。今回はKaggleが提供しているPythonイメージを利用します。
docker-composeはDockerfileのビルドと起動を管理するツールです。
Dockerコンテナを起動する際、いろいろなオプションをつけることができます。しかし、それをいちいちコマンドラインで打つのは煩雑です。docker-composeを使えば、様々なオプションをdocker-compose.ymlというYAMLファイルで設定することができます。
docker-composeは本来は複数のコンテナを連携して使うために作られたツールですが、今回はコンテナを簡単に立ち上げるためだけに使いたいと思います。
Dockerとdocker-composeのインストール
それでは、Dockerとdocker-composeをインストールしていきましょう。
既にインストール済みの方はこの節は読み飛ばしてください。
https://docs.docker.com/docker-for-mac/install/ に従ってDocker Desktop for Macをインストールします。
インストールが終わったら、アプリケーションからDocker.app
を起動します。(起動にはしばらく時間がかかるかもしれません)
Dockerが起動されたら以下のコマンドを打ち、dockerとdocker-composeのバージョンが表示されるか確認してください。
$ docker --version
$ docker-compose --version
Kaggle Kernelを元に分析環境を作る
それでは、Kaggleが提供しているDockerfileを元に、データ分析の環境を作っていきます。
今回は以下のようなフォルダ構成で解析を進めていくとします。
.
├── .dockerignore
├── Dockerfile
├── docker-compose.yml
├── input/ # データ
├── notebook/ # Jupyter Notebook
└── script/ # スクリプト
このうち、以下の3つのファイルは新しく作成します。
- Dockerfile
- docker-compose.yml
- .dockerignore
Dockerfile
Dockerfileは、イメージの定義です。どういうOSを使って、どういうライブラリをインストールするのか、という内容を書きます。
# kaggleのpython環境をベースにする
FROM gcr.io/kaggle-images/python:v56
# ライブラリの追加インストール
RUN pip install -U pip && \
pip install fastprogress japanize-matplotlib
内容はこれだけです。
FROM gcr.io/kaggle-images/python:v56
は、Google Container Registry(gcr.io)上にあるKaggle公式Dockerイメージを出発点にしてイメージを定義する、という意味です。
gcr.io/kaggle-images/python
には、既にnumpyやpandasを始めとして、データ分析に必要な多くのライブラリが含まれています。
:v56
はタグの指定です。KaggleのDockerイメージは日々改善されているので、今の時点での最新版を書いておくと良いでしょう。タグの一覧はgcr.io/kaggle-images/pythonにアクセスすると見ることができます。
:latest
と指定して最新版を入れることもできますが、イメージが更新されるたびにダウンロードが走ってしまいますし、環境がころころ変わるのは望ましいことではないので、バージョンを特定しておくことをおすすめします。
もし足りないライブラリがあるならば、 RUN
コマンドを使うことで pip install
をすることができます。
docker-compose.yml
docker-compose.yml
にはコンテナを起動する際の設定を書きます。
version: "3"
services:
jupyter:
build: .
volumes:
- $PWD:/tmp/working
working_dir: /tmp/working
ports:
- 8888:8888
command: jupyter notebook --ip=0.0.0.0 --allow-root --no-browser
version
はdocker-compose.ymlの書き方のバージョンです。3を指定しておけばよいかと思います。
services
以下に起動するコンテナの設定を書いていきます。jupyter
はコンテナを管理するための名前です。
build: .
は同じフォルダにあるDockerfileをビルドする、という意味です。先程作成したDockerfileがビルドされます。
volumes
はマウントするフォルダの設定です。$PWD:/tmp/working
とすることにより、現在のディレクトリを、Dockerコンテナ上の/tmp/working
に紐付けることができます。これにより、Dockerコンテナの中からでも現在のディレクトリ(とその中のデータとか)にアクセスすることができます。
working_dir
はコンテナ内の初期ディレクトリの設定です。今回は/tmp/working
に設定しています。
ports
はポートフォワードの設定です。手元のポート:コンテナのポート
の形式で書きます。
ふだんJupyter Notebookを起動するとき、localhost:8888
からアクセスすることになるかと思います。今回はDockerコンテナ上でJupyterを起動するため、Dockerコンテナ内のlocalhost:8888
にアクセスしないとJupyterを見ることができません。しかし、portsの設定をしておくことで、Dockerコンテナ内の localhost:8888
を手元のlocalhost:8888
につなぐことができます。
command
はDockerコンテナを起動したときに走るコマンドの内容です。今回はJupyter Notebookを起動しています。
いくつか見慣れないオプションがついているかと思います。
--ip=0.0.0.0
は起動したJupyter Notebookにコンテナ外からアクセスできるようにするオプションです。
--allow-root
はルートでの実行を許可するオプションです。Dockerコンテナはデフォルトでルート権限で起動するので、このオプションが必要です。
--no-browser
はJupyter Notebook起動時にブラウザを立ち上げないオプションです。
.dockerignore
.dockerignoreは、Dockerfileをビルドする際に無視するファイルを列挙するものです。
今回の場合、データやノートブックはDockerfileのビルドの瞬間は必要ありませんから、.dockerignore
に書いておきましょう。(コンテナとのデータの共有は、ビルドを行った後にマウントで対応します)
input
notebook
script
input/
などに大容量のデータが入っていて、かつ.dockerignore
に記述もしなかった場合、Dockerのビルドの際に時間がかかるようになってしまいます。ビルドに必要の無いファイルやフォルダは、.dockerignore
に書くように心がけましょう。
起動してみる
それでは、実際に分析環境を起動してみましょう。
ここで注意ですが、この操作は初回時に限りめちゃめちゃ重いデータをダウンロードする必要があります。実は、Kaggleの公式イメージは便利なライブラリがたくさん入っている反面、とても重いDockerイメージになっています。その容量、なんと18GB!
学校や職場など、WiFi環境が整っている場所で行ってください。間違ってもテザリング中なんかにやらないようにしてくださいね。
$ docker-compose up --build
まず、最初にDockerfileのビルドが走り、その後Dockerコンテナの中でJupyter Notebookが起動されます。最後のJupyter Notebookが起動するところはだいたいこんな感じのログになるかと思います。
jupyter_1 | [I 07:11:32.796 NotebookApp] Writing notebook server cookie secret to /root/.local/share/jupyter/runtime/notebook_cookie_secret
jupyter_1 | [I 07:11:33.065 NotebookApp] JupyterLab extension loaded from /opt/conda/lib/python3.6/site-packages/jupyterlab
jupyter_1 | [I 07:11:33.065 NotebookApp] JupyterLab application directory is /opt/conda/share/jupyter/lab
jupyter_1 | [I 07:11:33.068 NotebookApp] Serving notebooks from local directory: /tmp/working
jupyter_1 | [I 07:11:33.069 NotebookApp] 0 active kernels
jupyter_1 | [I 07:11:33.069 NotebookApp] The Jupyter Notebook is running at:
jupyter_1 | [I 07:11:33.069 NotebookApp] http://33c518cf1679:8888/?token=hogefugatoken
jupyter_1 | [I 07:11:33.069 NotebookApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).
jupyter_1 | [C 07:11:33.069 NotebookApp]
jupyter_1 |
jupyter_1 | Copy/paste this URL into your browser when you connect for the first time,
jupyter_1 | to login with a token:
jupyter_1 | http://33c518cf1679:8888/?token=hogefugatoken
最後のlogin with a tokenの下のURLをコピーし、33c518cf1679
の部分をlocalhost
に変えてブラウザのURLバーに入れればJupyter Notebookにアクセスできます。
ローカルにあるファイルにもアクセスできることを確認してください。
まとめ
今回はDockerとdocker-composeを使い、Kaggleの環境をベースにした分析環境の立ち上げを行いました。
自分なりにカスタマイズしたDockerfileを持っておけば、新しいデータが来たときも迅速に解析に取り掛かることができます。
みなさんもぜひ試してみてください。
- 作者: 山田明憲
- 出版社/メーカー: 技術評論社
- 発売日: 2018/08/25
- メディア: Kindle版
- この商品を含むブログを見る
追記 (2019/05/13)
Twitterでmhiro2さんにいただいた指摘を元に記事を修正しました。ありがとうございました!
Docker Hub のイメージは古いので、https://t.co/mGMtjYLeFK を使った方がより現行カーネルの環境に近くライブラリも新しいと思います。fastprogress も カーネルでは既に使えますし、gcr の方の latest だと入ってるみたいです。GPU 前提ならビルドするしかないので、NGC 使うのがベターですね。
— mhiro2 (@mhiro2_1127) 2019年5月13日
追記2 (2019/07/12)
Dockerのメモリ上限を大きくする方法についてu++さんが書いてくださいました。メニューバーのDockerマークから設定に飛び、メモリ上限を拡張してください。