Docker入門して機械学習環境構築

f:id:karaage:20190516000848p:plain:w640

機械学習の環境構築のために今更ながらDocker入門

 最初に、この記事の対象者は、私のように趣味で機械学習しているエンジョイ勢や学生さん、初心者が対象です。インフラなど本職での運用などは全く想定しておりませんので、ご承知おき下さい。詳しい方は色々教えていただけると嬉しいです、それか生暖かく見守っておいて下さい。

 というわけで、今更ながら機械学習の仮想環境としてDockerがとても優秀であることに気づいたので、Dockerに入門してみました。Dockerは何か?という基礎的な解説は、以下のさくらインターネットさんの記事が非常に分かりやすかったので、以下参照下さい。

 仮想環境に関しては、Virtual Machine・Pyenv/Virtualenv等があり、今まで実際に試してきました。詳細は以下記事参照下さい。

 これらに対するDockerとの違いを、自分なりにまとめた表が以下です(ざっくりとした自分の理解です、細かい違いはご容赦を)。

仮想化環境比較
仮想化環境比較

 こうしてみるとDockerはVirtual Machineと*env系の良いとこどりといった感じですね(悪く言えば中途半端)。実際使ってみて私が実感したDockerの機械学習の環境としてのメリットは以下です。

  • ローカルマシンで構築した環境をサーバー上のマシンで一瞬で構築できる
  • 今ある環境を壊さずに使い捨てのテスト環境を一瞬で構築・破壊できる
  • 環境まるごとイメージ化できるので問題の出やすいバージョン依存関係エラーが起きない
  • DockerHubという公開ファイルサーバーに無料で大きいイメージファイルをバックアップできる
  • 便利な環境が揃ったDockerイメージが豊富にある

 特に良いなと思ったのが、イメージ化してバージョン固定した環境をいくつも手軽に保存できるところですね。特にディープラーニング(深層学習)はバージョン関係の依存関係が激しいので助かります。

 というわけで、ネットで調べつつDockerで一通り環境構築をやってみたのですが、結構はまったところが多かったので、個人的なメモとしてやったことや、参考にした情報源をまとめておきます。目標として、東大松尾研が先日無料で公開を開始した機械学習の学習教材「DL4US」の環境をDockerで構築して学習してみるところまでをゴールに使い方を一通り説明していきたいと思います。

 手っ取り早く「DL4US」の環境構築方法のみを知りたいという方は、Qiitaに環境構築のみにフォーカスした記事を投稿したので以下参考にしてください。

東大松尾研が無料で公開しているディープラーニングの実践的教育プログラム「DL4US」の学習環境をDockerを使ってコマンド一発で構築する方法 - Qiita

Docker使用方法

Docker Hubにサインイン

 DockerHubのサイトでユーザー登録をしておきます。便利なイメージがたくさんある上に自分のイメージを公開することもできる凄いサイトです。これからたくさんお世話になりますので、仁義を切っておきましょう。

MacでDockerをインストールする場合

 公式サイトでのインストールマニュアルは以下です。

 Homebrewを使ってもインストールできます。以下コマンドでOKです。

$ brew install docker
$ brew cask install docker

 Homebrewに関しては、以下記事参照下さい。

 インストールして、ターミナルで動作確認して下さい。以下のようにバージョン確認コマンドでバージョンが表示されたらOKです。

$ docker --version
Docker version 18.09.6, build 481bc77

 続いて、以下コマンドでDockerを起動します。

$ open /Applications/Docker.app

 すると以下のような画面が表示されるので、先ほど登録したIDとパスワード入力します。

f:id:karaage:20190515010158j:plain:w480

 これでDockerのセットアップは完了です。

LinuxでDockerをインストールする場合

 下記リンク先記事のDockerのインストールの箇所ままでOKでした。

nvidia-dockerを使用してGPU環境構築 - Qiita

 コマンド多くて煩雑なので、コマンド一発でセットアップできるスクリプトを作成しました。以下2行でOKです。もしよろしければご利用下さい。

$ wget https://raw.githubusercontent.com/karaage0703/ubuntu-setup/master/install-docker.sh
$ ./install-docker.sh

 上記スクリプトを実行すると、Macと同様、ユーザー権限(sudo無し)でDockerが使えるようになります。注意点は、一回ログアウトしてからログインし直す必要がある点です(そうしないとユーザー権限でdockerを起動できませんでした)。

 更にnvidia-dockerを使用すれば、Docker上でCUDAを使用してディープラーニングができたりしますが、詳細は今回は省略します(ハード依存、バージョン依存等が激しすぎるので)。インストールしたい方は、冒頭で紹介した記事を参照下さい。また、CUDA周りでハマった時のメモをQiitaに書いていますので、もしはまった方は参考にしてみて下さい。

TensorFlowでGPU学習させるためにCUDA周りではまったときの対処法 - Qiita

 また、nvidia-dockerでのTensorFlowでのGPU動作確認に関しては、私の環境では以下のコマンドでコンテナを立ち上げると、手軽にMNIST等の動作確認ができてよかったです(記事通りではうまくいきませんでした)。このコマンドの詳細や、確認に関してはこれ以降の記事を参照ください。

$ nvidia-docker run -it --rm --name tensorflow-gpu -p 8888:8888 tensorflow/tensorflow:latest-gpu-py3-jupyter

WindowsでDockerをインストールする場合

 未実施です。以下が詳しそうです。

Dockerの基本的な使用方法

 ここからは、各OSで操作は共通です(Windowsは差分があるかもしれません)

Dockerイメージをダウンロード

 Dockerは、以下の流れで使用します。

  • Dockerイメージをダウンロード(Docker Pull)
  • ダウンロードしたDockerイメージからコンテナを起動させる

 Dockerのイメージは無数にあります。例えば、以下の様にTensorFlowのDockerイメージをpullすると、一瞬でTensorFlowの環境が手に入ります。

$ docker pull tensorflow/tensorflow

 イメージを探したいときは、以下で探せます。

$ docker search 'numpy'

 ダウンロードしたイメージを確認したいときは以下です。

$ docker images

コンテナを起動させる

 次に以下コマンドで、先ほどダウンロードしたTensorFlowのDockerイメージを用いてコンテナと呼ばれるDockerでの仮想環境を立ち上げます。

$ docker run -it --rm --name tensorflow tensorflow/tensorflow

 オプションの意味は以下です。

-it:ターミナルを使うためのオプション
--rm:コンテナから抜けるとコンテナを自動で削除する
--name: コンテナの名前を指定する

 オプションの詳細や、他のコマンド等に関しては、以下の公式リファレンスを参照しましょう。

Docker run リファレンス — Docker-docs-ja 17.06.Beta ドキュメント

 また、実はイメージをダウンロードする前にコンテナを起動したら、勝手にイメージをダウンロードしてくれるので、ダウンロード前にいきなりコンテナを起動させてもOKです。

 コンテナが起動すると、以下の様な画面が出て、自動的にターミナルにログインします。

________                               _______________                
___  __/__________________________________  ____/__  /________      __
__  /  _  _ \_  __ \_  ___/  __ \_  ___/_  /_   __  /_  __ \_ | /| / /
_  /   /  __/  / / /(__  )/ /_/ /  /   _  __/   _  / / /_/ /_ |/ |/ / 
/_/    \___//_/ /_//____/ \____//_/    /_/      /_/  \____/____/|__/


WARNING: You are running this container as root, which can cause new files in
mounted volumes to be created as the root user on your host machine.

To avoid this, run the container by specifying your user's userid:

$ docker run -u $(id -u):$(id -g) args...

root@xxxxxxxxxx:/# 

 あとは、好きなLinuxコマンドを打ち込みましょう。例えばlsコマンドだと結果は以下です。

# ls
bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

 ここで、面白いのがこの環境はあくまでDockerイメージ固定の仮想環境上である点です。なので、この上で何をしても再度同じイメージでDocker runすると、何事もなかったように元の環境が復活します。例えば、普段だと絶対にできない、以下のような危険コマンドだってDocker上なら思う存分実行できます。絶対に普段の環境で真似するなよ!絶対だぞ!

# rm -rf

 シェルは、exit を入力するか Ctrl + D で終了することができます。

ホストとコンテナでファイル共有

 すぐ環境復帰できるのは便利ですが、このままではDocker上でせっかく開発したソフトや出力した結果も、Dockerイメージを立ち上げるたびに消えてしまいます。また、ホスト側で開発したプログラムをDocker上で走らせることもできませんね。

 そこで、今度は以下のようなコマンドでDockerを走らせます。

$ docker run -it -v $PWD/docker_share:/share --rm --name tensorflow tensorflow/tensorflow

 違いは-vというオプションです。-v host directory:contena directory と指定することで、ホスト側とコンテナ側のディレクトリを共有できます。

 上記コマンドを実行すると、コマンド実行したディレクトリの下に docker_share というディレクトリが生成されるので、そこに適当なファイルをコピーしてみて下さい。コンテナ側で# ls /share とすれば、コピーしたファイルが見えるのが分かると思います。逆にコンテナ上で /shareディレクトリにファイルを入れると、ホスト側にも共有されます。

 ホスト側にインストールされている任意のエディタで開発したいときは、ファイル共有したホストのディレクトリ上で開発していくのが良いのかなと思います。VS CodeでSSHアクセス手段もあるようですが、以下の点でDockerの場合はあまり適さないかなと個人的には思っています。

  • 拾ってきたDockerイメージそのままでは使えない
  • 他のエディタの対応ができない(or 大変)

コンテナで起動したJupyter Notebookにホストのブラウザからアクセス

 便利な使い方として、コンテナ内で起動したJupyter Notebookに、ホストのブラウザからアクセスすることができます。

 これ使えば、複数のPython環境を立ち上げておいて、並列に走らせるといったことも簡単にできてしまいそうですね。

 Jupyter Notebookが入ったDockerイメージとしてdatascience-notebookといういかにもな名前のイメージを使用します。では、Dockerイメージをダウンロードして、コンテナを起動しましょう。今回は、docker pullを省略していきなりコンテナ起動してみます。

$ docker run -p 8888:8888 -it --rm --name ds jupyter/datascience-notebook

 勝手にイメージのダウンロードが始まり、コンテナが起動します。起動すると画面に token=xxxxxxxxxxxxxx という形でtokenが表示されます。

 続いて、ブラウザで以下のアドレスにアクセスしましょう。

http://localhost:8888

 以下のように表示されるので、先ほどのtokenをコピペするとログインできます。

f:id:karaage:20190515012053p:plain:w640

 もしくは、以下のようにアドレスにtokenを打ち込めば、ログイン画面を省略して直接Jupyter Notebookにログインできます。

http://localhost:8888/?token=xxxxxxxxxxxxxx

 ログインすると、以下のようにJupyter Notebookが表示されます。

f:id:karaage:20190515012319p:plain:w640

 PyenvやAnaconda使った時は、環境構築にたくさんコマンドを入力する必要がありましたが、DockerだったらDockerさえインストールしておけば、MacでもLinuxでもイメージをダウンロードしてコンテナを起動するだけで、同じ環境が手に入るのでスマートですし楽々ですね。素晴らしいです。

 ちなみに、普通にコンテナのターミナルにログインしたい場合は以下の通りです。jovyanというjupyter notebookのユーザーを意味するユーザー名でログインします。

$ docker exec -it ds bash

 もし、apt-getなどsudoが必要なコマンドを実行したい場合は、本記事末尾のTIPSを参照下さい。

Dockerイメージの作成(保存)

 また、色々開発に必要なソフトをインストールしたら、コンテナの環境ごとイメージ化して保存したいですね。

 Dockerのイメージを作成する方法は、以下3つあります。

  • コンテナからイメージ作成
  • Dockerfileからイメージ作成
  • GitHubとDockerHubを連携させてイメージ作成

 下に行くほど高度になりますが、色々メリットがあります。順に説明していきます。

コンテナからイメージ作成

 先ほど起動したdsというコンテナで作業したあと、以下を実行するとkaraage0703/ds-imageというイメージを保存できます。

$ docker commit ds karaage0703/ds-image

 イメージの名前は、Docker Hubを用いて自分のイメージを公開したい場合は、以下の形式にする必要があります。

<Docker Hub ユーザ名>/<リポジトリ名>

 Docker Hubで公開する必要がなければ、ds-imageといった単純な名前でも構いません。

 このイメージを以下コマンドでdocker runすると、イメージ化したときの環境でコンテナが起動します。

$ docker run -it --rm --name ds karaage0703/ds-image

Dockerfileからイメージ作成

 Dockerfileというコード(テキストファイル)からイメージを作成することもできます。

 まずは、以下のようなDockerfileを好きなエディタで作成して下さい。

FROM ubuntu
MAINTAINER karaage0703 <coldchicken@gmail.com>
RUN apt-get update && apt-get install -y python3.7

 あとは、Dockerfileがあるディレクトリで以下実行すれば、Dockerfileを元にしたイメージができあがります(コマンドの最後にコロン.があるので忘れずに)。

$ docker build -t karaage0703/test-image .

 Dockerfileを使う良さは、作成したイメージがどのような環境なのか後で一目で分かることですね。作成したイメージを元に、変更を加えることも簡単にできます。

 Dockerfileの書き方は、非常に奥が深いのでこの記事では解説しません。本記事最後の参考リンクを参照下さい。

 Dockerfileを1から作成するのは大変そうなので、自分がやりたいことに必要な環境に近いDockerfileを探して、それをベースに作成するという形が良さそうです。

作成したDockerイメージをDockerHubへアップロード

 作成したイメージをDockerHubへアップロードする方法は簡単で、Docker HubにログインしてpushするだけでOKです。具体的には、以下2つのコマンドを打つだけです。

$ docker login
$ docker push karaage0703/test-image

 アップロード後、Docker Hubにログインすると、以下のようにイメージがアップされていることが確認できました。 f:id:karaage:20190515013541p:plain:w640

 Docker Hubのイメージはネットで公開されているので、これで世界中の誰もが自分の作ったオリジナルの環境を構築することが可能となります。素敵ですね。

 Docker Hubはプライベートイメージは、無料アカウントだと1個までで、公開イメージはなんと無制限のようです。めちゃめちゃ太っ腹ですね。複数のプライベートイメージが必要な場合は課金しましょう。

GitHubとDockerHubを連携させてイメージ作成

 さらにGitHubとDockerHubを連携させることで、DockerfileをGitHubにpushするだけで、自動的にそのDockerfileのイメージを作成することまでできます。

 イメージの共有とバックアップが捗りますね。めちゃ便利です。

 全体のイメージは、以下サイトの記事がわかりやすいです。

 実際の設定方法に関しては、以下サイトが参考になりました。

 GitHubに「Dockerfiles」というリポジトリを作成して「dl4us」というディレクトリを作成しその中に「Dockerfile」をアップします。そのあとの、Docker Hubでの設定は以下となります。 f:id:karaage:20190517001832p:plain:w640

良さそうなDockerイメージの一覧

 とりあえず使えそうなDockerイメージをメモしておきます。

jupyter/datascience-notebook

jupyter/tensorflow-notebook

JupyterのDockerイメージまとめ - Qiita

Dockerで基本的なData Science環境(Jupyter, Python, R, Julia, 定番ライブラリ)を構築する。 - Qiita

DockerのTIPS(テクニック)

 便利なテクニック等です。

起動したコンテナを一括で削除(停止)する

$ docker rm $(docker ps -aq)

jovyanユーザーでsudoが使えない

 以下コマンドのようにオプションをつけると、rootでログインできるようになります。

$ docker run -p 8888:8888 -it -e GRANT_SUDO=yes --user root --rm --name ds jupyter/datascience-notebook

<none> のイメージを削除

 いつの間にか生まれる<none>というイメージを削除する方法

$ docker image prune

ディープラーニングの学習等大量にメモリを使うアプリで落ちる

 Dockerの設定で、メモリを最大まで増やしておきましょう。

f:id:karaage:20190519014243p:plain:w480

東大松尾研の機械学習

 一通りDockerの使い方を習得できたので、いよいよ高度なDeep Learning技術者を育成することを目的とした教育プログラムとしてうたわれる「DL4US」の学習環境をDockerで構築し、学習していきます。

 学習環境構築にあたっては、Dockerfilesを作成して、GitHubにアップロードしたのち、DockerHubのAutomated Build機能でイメージを作成しました。DockerfilesファイルとDockerイメージは以下になります。

DockerHub dl4us image(要DockerHubログイン)

 DockerHubに公開しているので、使用するのは簡単でDockerをインストールしたら、以下コマンドを入力するだけです。自動的にDockerイメージがダウンロードされ、コンテナが起動するはずです。

$ docker run -p 8888:8888 -it --rm --name dl4us karaage0703/dl4us

 次に以下コマンドでコンテナにログインします。

$ docker exec -it dl4us bash

 コンテナ内のシェルで以下コマンドを実行し「dl4us」をダウンロードします。

# cd work && git clone https://github.com/matsuolab-edu/dl4us

 後はJupyter Notebookにログインして、実行しながら学習をすすめていくだけです。

f:id:karaage:20190517002039p:plain:w640
 学習の様子

 ちなみに、まだ全てのチュートリアルでの動作確認ができていないことはご了承下さい。lesson7の一部でエラーが発生することは確認しております。

まとめ

 今更ながらDocker入門しました。具体的には、一通りの操作を習得し、松尾研の無料教材「DL4US」の環境をDocker上に構築し、DockrHubで公開するまでをやってみました。

 実際使ってみて、Dockerの便利さを痛感しています。今後、もしディープラーニングにAWS等のクラウドを使う時、ローカルマシンの環境をイメージ化しておけば、一瞬でサーバー上に(ほぼ)同じ環境を構築できることになるので更に便利そうです。Mac for Dockerのおかげで、LinuxマシンがなくてもLinuxの環境構築ができるのもありがたいですね。あと、nvidia-dockerを使えば、Docker上でCUDAも使えるようです(ただしCUDAはLinuxのみ)。

 あとはRaspberry Pi(ラズパイ)やJetson NanoでもDockerを使うと良いかなーとも思ったのですが、ラズパイやJetsonはArmなのでMacやLinuxで作ったDockerイメージをそのまま使えないのであまり嬉しさはないかもしれませんね。

 いずれにせよDockerメリットが色々ありますので機械学習の環境構築で悩んでいる方は、一度Dockerを検討してみる学習が捗るかもしれません。

参考リンク

Dockerfileの書き方

Dockerfileを書くためのベストプラクティス【参考訳】v18.09 - Qiita

Dockerfile を書くためのベストプラクティス解説編

Dockerfileを書いてみる - Qiita

効率的に安全な Dockerfile を作るには - Qiita

Dockerfile のベストプラクティス — Docker-docs-ja 1.9.0b ドキュメント

Docker入門(第四回)~Dockerfileについて~ | さくらのナレッジ

環境構築関係

Docker入門(第一回)~Dockerとは何か、何が良いのか~ | さくらのナレッジ

機械学習を勉強するときはDockerを使うと便利 - あさのひとりごと

Dockerを使って機械学習の環境を作ろうとした話 - Qiita

nvidia-dockerを使用してGPU環境構築 - Qiita

nvidia-docker でポータブルな機械学習の作業環境を作る - Qiita

Tensorflowのdockerを使ってみる(macOS) - Qiita

Ubuntu 16.04 LTS で NVIDIA Docker を使ってみる - CUBE SUGAR CONTAINER

データサイエンスのためのAnaconda環境構築とTensorflowのインストール方法(Docker編) | Casual Developers Notes

Dockerで作る機械学習研究開発環境

DockerでDeep Learningなどの環境をドカドカ構築 - Qiita

GCPとDockerでKaggle用計算環境構築 - Qiita

TIPS

DockerをHomebrewでMac OSに導入する方法 - Qiita

dockerによるお手軽jupyter環境構築 - Qiita

関連知識

個人的に気になっている仮想化技術等に関するメモ - Qiita

関連記事

変更履歴

2019/05/22 Qiita記事へのリンク追加