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行(curlがインストール済みなら1行)でOKです。もしよろしければご利用下さい。

$ sudo apt install -y curl
$ curl -s https://raw.githubusercontent.com/karaage0703/ubuntu-setup/master/install-docker.sh | /bin/bash

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

 さらにGPUをDocker上で使用したい場合は以下記事参照ください。

DockerでのディープラーニングGPU学習環境構築方法 - Qiita

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 ドキュメント

 また、実はイメージをダウンロードする前にコンテナを起動したら、勝手にイメージをダウンロードしてくれるので、ダウンロード前にいきなりコンテナを起動させても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のイメージを作成することまでできます。

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

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

http://dr-asa.hatenablog.com/entry/2017/08/21/185301(リンク切れ)

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

 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上でGPUを使用する場合

 NVIDIA Container Toolkit(NVIDIA Docker)を使用すれば、Docker上でCUDAを使用してディープラーニング環境を構築することも可能です。詳細は以下記事参照ください。Linux上でDockerを使う前提です。

DockerでのディープラーニングGPU学習環境構築方法 - Qiita

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

$ 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のGUI環境を構築する

 DockerでGUI(デスクトップ)環境を構築する場合、VNCを活用するのが一番手軽そうです。DockerのHost側でVNCサーバーを立ち上げて、クライアント側でVNC接続をするとGUI環境を使用できます。

 具体的には、VNCサーバー環境が構築された、良いUbuntuのDockerイメージがあるのでこれを使用します。以下コマンド実行すると、Dockerイメージがダウンロードされ(初回のみ)、VNCサーバーが自動起動します。

$ docker run -p 5901:5901 queeno/ubuntu-desktop

 後は、クライアント側からVNCでアクセスするだけです。Macなら「Ctrl + K」で以下アドレス入力するだけです。

vnc://localhost:5901

 詳細は、以下参照下さい。

dockerで手軽にLinuxデスクトップ環境を試せる! - KOKENSHAの技術ブログ

GitHub - queeno/docker-ubuntu-desktop: Ubuntu 16.04 with ubuntu-desktop and vncserver

DockerのGUIにブラウザからアクセスする

 DockerのGUIにブラウザでアクセスすることもできます。以下記事では、ROSのGUI環境をDocker上に構築しています。

Docker上でGUIのROS1/ROS2を一瞬でセットアップする方法 - Qiita

Docker上でホストのデバイスを認識する

 例えばホストのUSBデバイス(USBカメラ等)をDockerで使用したい場合です。Linuxの場合は--privilegedオプションをつけて起動すればOKです。

 Macの場合は少し複雑ですので割愛します(Googleで検索してみてください)。

Dockerで機械学習のチュートリアル実践

東大松尾研の機械学習

 一通り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の一部でエラーが発生することは確認しております。

データサイエンス100本ノック

 データサイエンス協会が提供するデータサイエンス初学者のための実践的な学習環境です。

 詳細は以下のQiita記事参照ください。

まとめ

 今更ながら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を検討してみる学習が捗るかもしれません。

参考リンク

Dockerの基礎知識

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

世界一わかりみの深いコンテナ&Docker&Kubernetes入門 - Speaker Deck

Dockerハンドブック

Dockerfileの書き方

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

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

Dockerfileを書いてみる - Qiita

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

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

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

機械学習なdockerfileを書くときに気をつけとくと良いこと - nykergoto’s blog

Docker環境構築関係

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

機械学習を勉強するときはIDEっぽいJupyterLabを使うと便利 - あさのひとりごと

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 Note

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

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

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

Dockerを体系的に学べる公式チュートリアル和訳 - Qiita

DockerのTIPS

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

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

Docker関連知識

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

関連記事

変更履歴

  • 2020/08/07 NVIDIA Dockerに関してリンク追記
  • 2020/07/11 参考リンク追記
  • 2020/06/24 Dockerで実践するチュートリアル追加。構成を修正
  • 2020/02/17 DockerのGUI環境へのブラウザでのアクセスに関して追記
  • 2019/12/31 DockerでのGUI環境に関して追記
  • 2019/11/14 NVIDIA Dockerに関して最新情報へのリンク追記
  • 2019/05/22 Qiita記事へのリンク追加