📜 要約
コンテナー管理ソフトウェアのDockerを利用することで、データ分析の場面で利用頻度の高いRおよびPythonの分析環境として実行することが出来るRStudio Server、Jupyter、Beaker Notebookを容易に構築可能になる。Dockerを使うことの利点として、複数人でのデータ分析や将来の利用面においてデータ分析結果の再現性を高められると考えられる。
🍵 前置き〜データ分析者が直面する再現性への挑戦
データ分析の結果が、自分以外では再現できない、同じデータを使っているのにナンデ!?ということが時々あります。その原因として多いのが分析に関わる人間が利用する実行環境の違い、です。大きなものではOS、小さなものでは分析に利用するツール本体や拡張機能(パッケージやモジュール)のバージョンの違いがあります。
こうした再現性の問題は、複数人でデータ分析を行う時だけでなく、個人で分析を進めていく際にも気をつけていきたいところです。昔やった分析結果を将来再現できるなんて保証はありません。
使用環境についてメモを残しておくことは大事でしょう。しかし、そうしたメモ書きがあっても同様の環境を構築することは面倒であり、手間のかかるものです。使用環境のメモ書きは分析を再現する際に参考にはなりますが、実用的ではありません。
🐳 Dockerをベースにした分析環境の構築
ではどうするか、という問いに対して、Dockerを使うことが一つの解決策として考えられます。Dockerはオープンソースのコンテナー管理ソフトウェア(しばしば仮想マシンと比較される)の1つであり、エンジニアの開発場面で利用される機会の多いツールです。
しかし、Dockerが提供する仮想環境はデータ分析においても有効な機能を果たします。各地で言われていることですが、次にあげるようなDockerの特徴はデータ分析者の求める再現性を確保するためには理想に近いものでしょう。
- 軽量:Dockerでは仮想環境を動作させるためのファイルシステムがホストとなるコンピュータ内で共有される。ファイルシステムの差分しかディスク容量を消費しないため、必要以上の容量を必要としません。
- 共有のしやすさ:Dockerが構築するコンテナー型の仮想環境はDockerfileという設定ファイルによって記述されます。そのDockerfileを使えば、異なるコンピュータ上でも同じコンテナー型の仮想環境を作成することができます。ツールのバージョンや依存関係はDockerfileに依存しているので、共通の環境を構築できます。
RおよびPythonユーザーのためのDockerイメージ
データ分析の際に頻繁に利用されるRやPython(Julia, Rubyも)を利用している人には、RStudioやJupyter、Beaker Notebookといった分析ツールが人気かと思います。
Dockerでは、これらの分析ツールを仮想環境で実行するためのDockerイメージがDocker hubによって公開されており、容易に分析環境を構築することができます。独自の環境を構築していきたいという場合にも、最低限必要なツールなどの記述がすでに書かれているこれらをベースにするのが良いでしょう。
- RStudio Server
- rocker/hadleyverse… RStudio Server, LaTeX環境, モダンなRパッケージが含まれる
- rocker/rstudio
- Jupyter
-
jupyter/all-spark-notebook… Jupyter, Scala, R, Sparkなどが含まれる
-
- Beaker Notebook
- beakernotebook/beaker... Python, R, Groovy, Julia, Node, JavaScript, SQL, C++などをサポート
Jupyterについては@kshigeru さんの記事がすぐれています。Beaker NotebookのDockerイメージ利用についは@keiono さんの記事に詳しいです。再現性の問題も取り上げているので是非ご覧ください。
ここでは以下主にRユーザーを対象に、Rを分析環境として利用する場合の話を中心に扱います。なおイメージの編集方法やコミット、Dockerfileの作成などは共通です。
🔵 RStudio ServerをDocker環境で利用する
上記のhadleyverseイメージを使って、RStudio Serverを動作させてみましょう。すでにDockerが実行できる条件が揃っていれば、ターミナルで次のコマンドを実行してRStudio Serverが起動します。
docker run --rm -p 8787:8787 rocker/hadleyverse
最初の起動では、Docker hubから必要なファイルをダウンロードしてくるので時間がかかります。その間にDockerfileの中身を見て、どのようなものが含まれているか認識しておくのも良いでしょう。
hadleyverseについて補足
hadleyverseには主に以下のものが含まれます。いろいろなシステムを含んでいるためちょっと容量が大きいです。
- git
- TeX環境(texlive、ghostscript、imagemagick… )
- pandoc
- vim
- RおよびRStudio Server
- 各種のRパッケージ
hadleyverseを利用する際の日本語フォント周りを調整したDockerfileを@jnobuyuki さんが作成されています。日本語でのプロットを行う場合には参考にどうぞ。
上のような状態になったらローカルホスト内で起動していますので確認してみましょう。Dockerが利用するIPアドレスは、上記の画面にも出ていますがdocker-machine ip
でも確認できます。
ブラウザで http://192.168.99.100:8787/
を開くと、RStudio Serverへのログイン画面となります。先のコマンドではユーザーを指定しなかったので、ここでは以下のような入力をしてログインします。
- Username: rstudio
- Passward: rstudio
無事にログインできたでしょうか。あとは普段通り、分析を進めることができます。
docker run オプション
先のdocker コマンドをもう一度見てみましょう。
docker run --rm -p 8787:8787 rocker/hadleyverse
--rm
オプションは、起動したコンテナを利用後に破棄するオプションです。hadleyverseのような大きなイメージを利用する場合、docker コンテナが残っているとディスク容量を圧迫するので削除するのが良いでしょう。
-p
オプションおよび次の8787:8787
はポートフォワードを指定しています。
その他のdocker run
オプションとして以下のようなものがあります。
-
-d
… コンテナをバックグラウンドで動かす -
-e
… 環境設定 -
-v
… ホストディレクトリをコンテナにマウントする
特に大事になるのが-v
オプションです。-v
を指定することでローカル環境にあるファイル、ディレクトリを仮想環境と連携することが可能になります。
-v
は次のようにして記述します。
docker run --rm -p 8787:8787 -v /Users/uri/Desktop/liftr/:/home/rstudio/liftr rocker/hadleyverse
# liftr フォルダが home/rstudio/ 以下にできる
再びRStudio Serverを起動すると、きちんとliftr
フォルダがあります。-v
を使ってマウントしたディレクトリやファイルは
仮想環境で生成したファイルは自動的にローカル環境にも生成され、仮想環境で加えた変更はローカル環境のファイルにも反映されるという特徴を持ちます。
分析環境をオレオレ整備していく(コミットによるDockerイメージの作成)
rocker/hadleyverse
イメージにはすでに便利なRパッケージが含まれていますが、どうしてもそれ以上にRパッケージが必要になると思います。Dockerでは、既存のイメージを拡張していくための仕組みとして、commit
機能を備えています。次のような手順を踏んで、Dockerイメージをオレオレ環境に整備していきましょう。
まずはRStudio Server上で通常の方法でパッケージをインストールします。GitHubからパッケージをインストールするためのdevtools::install_github()
を使っても問題ありません。
install.packages("liftr")
devtools::install_github("hoxo-m/pforeach")
インストールが完了したら、ターミナルに戻り、Dockerで起動しているイメージを確認します。
docker ps
# CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
# a2f0d66896a2 rocker/hadleyverse "/init" About a minute ago Up About a minute 1410/tcp, 0.0.0.0:8787->8787/tcp sleepy_bell
ここでのCONTAINER IDを対象に変更をコミットします。commit
では、CONTAINER IDに加え、メッセージとイメージ名が必要になります。
docker commit -m "add packages" a2f0d66896a2 hoxom_verse
# sha256:335c72a5025896439a30cea4a3372c82e76a356b11ccef8b6549dfd2337d715f
その後イメージの一覧を表示してみると、先ほどコミットしたhoxom_verse
イメージが追加されています。
docker images
# REPOSITORY TAG IMAGE ID CREATED SIZE
# hoxom_verse latest 335c72a50258 2 minutes ago 2.839 GB
# rocker/hadleyverse latest 7cba8b06f25e 2 weeks ago 2.838 GB
コミットしたhoxom_verse
イメージはrocker/hadleyverse
をベースにしており、追加した2つのパッケージが利用可能な状態となっているので、以降はこちらを利用するようにします。
docker run --rm -p 8787:8787 hoxom_verse
もしイメージが不要になったらdocker rmi <IMAGE ID>
で削除することができます。
Dockerfileでオレオレ環境を作る
Dockerfileは、Dockerイメージを作成するために必要な設定ファイルです。Dockerfileを利用することで、第三者の環境でも共通の環境が構築することが可能になります(Docker hubはこの仕組みを利用)。
Dockerfileは次のような記述をします。
FROM <image> 元となるイメージを指定する。:の後ろでタグ指定可能
MAINTAINER <name> 管理者の名前
RUN <command> ビルド中に実行したいコマンドを指定。パッケージのインストールとか設定とか
CMD <command> 起動後のコンテナで実行したいコマンドを指定する。1つしか書けない
EXPOSE <port> [</port><port> ...] 外部に公開するポートを指定
ENV <key> <value> 環境変数の設定
ADD <src> <dest> ファイルを配置。絶対パスで記述する
あらかじめ分析に必要な環境が決まっている場合は、こうしたDockerfileを書いておくと良いかもしれません。
{liftr}パッケージでR MarkdownをもとにしたDockerfileを生成する
さて、Dockerfileの記述はLinuxに慣れていないと訳がわからなかったりします。そこで便利なのが**{liftr}
パッケージです。{liftr}
**パッケージでは、R MarkdownファイルのYAML部分に必要な記述をしておくことで、自動的にDockerfileを生成してくれます。
使い方は、拡張子 Rmd
ファイルについて、Dockerfile生成のための記述を加えていくだけです。また、分析結果を仮想環境で検証するために、分析内容自体をファイルに記述しておくと、こちらも自動的で検証してくれます。
Dockerfileを生成するのに必要な箇所はRmd
ファイルのYAML部分に書いていきます。以下のようにliftrブロックの記述がDockerfileを生成するのに利用されます。
---
title: "Dockerized R Markdown Document"
author: "Uryu Shinya"
date: "`r Sys.Date()`"
output:
html_document
liftr:
from: "rocker/hadleyverse:latest"
maintainer: "Uryu Shinya"
maintainer_email: "suika1127@gmail.com"
latex: false
pandoc: false
cranpkg:
- kernlab
- liftr
ghpkg:
- "uribo/lab.note"
- "dichika/yeah"
---
{liftr}で使用されるオプションは以下のものがあり、maintainerとmaintainer_emailは必須項目となります。配布用に名前とメールアドレスを書いておきましょう。
- maintainer… Dockerfileの管理者名
- maintainer_email: Dockerfile管理者のメールアドレス
-
from: Dockerイメージのベースとなるイメージ。デフォルトではDocker hub内の
rocker/r-base:latest
が利用される。r-baseではRStudio Serverが含まれていないので、rocker/hadleyverse
としておくと良い - latex: LaTeX環境を整備するか否か(初期値ではfalse)。hadleyverseで構築されるので必要なし
- pandoc: Pandoc環境の構築(初期値でtrue)。こちらもhadleyverseに含まれている
- syslib
-
cranpkg: CRANからインストールしてくるパッケージ名を記述。バージョンと併せて表記することで特定のバージョンがインストールされる(
e.g. ggplot2/1.0.0
)。バージョンを省略すると最新版がインストールされる - biocpkg: Bioconductor に登録されているパッケージをインストール
-
ghpkg: GitHubにリポジトリがあるRパッケージをインストール。
username/repository
という表記をする
ではDockerfileを生成してみましょう。関数lift()
にR Markdownのパスを渡します。
library(liftr)
lift("~/Documents/liftr/lift_docker.Rmd")
Dockerfileは次のようになりました。このDockerfileをビルドすることで、このDockerfileによって構築される環境を簡単に再現できます。
FROM rocker/hadleyverse:latest
MAINTAINER Uryu Shinya <suika1127@gmail.com>
# System dependencies for required R packages
RUN rm -f /var/lib/dpkg/available \
&& rm -rf /var/cache/apt/* \
&& apt-get update -qq \
&& apt-get install -t unstable -y --no-install-recommends \
ca-certificates \
libssl-dev \
libcurl4-openssl-dev \
libxml2-dev \
libssh2-1-dev \
git
RUN Rscript -e "install.packages(c('devtools','knitr','rmarkdown','shiny','RCurl'), repos = 'https://cran.rstudio.com')"
RUN Rscript -e "source('https://cdn.rawgit.com/road2stat/liftrlib/fab41764ea8b56677d05c70c86225774164b6ca0/install_cran.R');install_cran(c('kernlab','liftr'))"
RUN Rscript -e "devtools::install_github(c('uribo/lab.note','dichika/yeah'))"
RUN mkdir /liftrroot/
WORKDIR /liftrroot/
docker build -t uribo/liftr ~/Documents/liftr/
docker run --rm -p 8787:8787 uribo/liftr
というわけで、分析に利用するR Markdownから直接Dockerfileを生成することができました。パッケージ管理が面倒になりがちなので、こうしたツールを利用するとDockerを使ったデータ分析環境の運営が楽になりそうですね。
Dockerについては「仮想化に必要なVirtualBoxを使わずに簡単に利用出来るようになる」という記事も最近出ており、ベータ版の利用登録しておくと、しばらくして承認が下りる状態なそうなので、春ということで皆さまぜひ試してみてはいかがでしょう。
(ちなみにRではパッケージのバージョンの差異による再現性が度々問題となるので、{packrat}というシステムもあります ref) packratで人類の拡大再生産に貢献する - 盆栽日記, Packratの使い道を考えてみた - Qiita)