PythonとJuliaですぐにデータ分析できる環境が欲しいアナタに捧ぐDockerfile

- 2019年も半分過ぎたというのにまだ**AnacondaのOS直接インストールでしかPythonのデータ分析環境を作ったことがない**というあなた!
- Julia 1.0が出てもう丸一年が経とうとしているのに**まだJuliaに触れていない**あなた! 

**だいぶマズイですよっっ !!**
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227776/bd736a6d-2814-174d-bc23-e63b3b7b3b3b.jpeg" width=800>

...はい、盛大な煽りから始めてすいません 笑
皆さん新しいPCでデータ分析用の環境用意しようってなったときどうしてますか? 最近だとGoogle Colaboratoryという神ツールがあるおかげで敢えてローカルの環境を用意する必要性も薄れてきている感はありますが、それでも時々手元でJupyterを動かしたいという場面は少なからずあるでしょうし、最近Juliaがアツいらしいからちょっと触ってみたいけど公式は英語ばっかで読み解くのしんどい...とか、導入ミスって開発環境汚したくない...なんていう声もあるかと思います。

そういう時Dockerに習熟していればサクッと自分好みの環境を用意できますが、開発にあまり詳しくないデータアナリストの方や自分のように研究でちょこっとPythonやJuliaを使いたい大学院生にDockerfileをゼロから書けと言われてもなかなかしんどいというのが本音ではないでしょうか。

そこで**Python or Juliaでデータ分析用の環境をつくりたいけどDockerでの環境構築にあまり自信がない**という方のためにPythonとJuliaを使ったデータ分析に必要なパッケージ(PythonとJulia本体の導入も含む)とツール群(pandoc, tex, git, Jupyterなど)を盛り込んだDockerfileを用意しましたので、ぜひお役立てください。なおDocker本体のインストール手順は省略します。

```dockerfile:Dockerfile
# Minicondaやtexのインストールなどはjupyter/minimal-notebookとその親であるjupyter/base-notebook で行っているので、詳細が知りたい場合はDocker Hubの該当するイメージを覗いてください
ARG BASE_CONTAINER=jupyter/minimal-notebook
FROM $BASE_CONTAINER

USER root

# ffmpeg for matplotlib anim
RUN apt-get update && \
    apt-get install -y --no-install-recommends ffmpeg && \
    rm -rf /var/lib/apt/lists/*

USER $NB_UID

# Install Python3 packages
# 追加で入れたいパッケージが出てきたらここに追加して再度Dockerイメージをビルドしてください
RUN conda install --quiet --yes \
    'conda-forge::blas=*=openblas' \
    'ipywidgets=7.5*' \
    'pandas=0.24*' \
    'numexpr=2.6*' \
    'matplotlib=3.0*' \
    'scipy=1.2*' \
    'seaborn=0.9*' \
    'scikit-learn=0.20*' \
    'scikit-image=0.14*' \
    'tensorflow=1.13*' \
    'keras=2.2*' \
    'sympy=1.3*' \
    'cython=0.29*' \
    'patsy=0.5*' \
    'statsmodels=0.9*' \
    'cloudpickle=0.8*' \
    'dill=0.2*' \
    'dask=1.1.*' \
    'numba=0.42*' \
    'bokeh=1.0*' \
    'sqlalchemy=1.3*' \
    'hdf5=1.10*' \
    'h5py=2.9*' \
    'vincent=0.4.*' \
    'beautifulsoup4=4.7.*' \
    'protobuf=3.7.*' \
    'xlrd'  && \
    conda clean --all -f -y && \
    # Activate ipywidgets extension in the environment that runs the notebook server
    jupyter nbextension enable --py widgetsnbextension --sys-prefix && \
    # Also activate ipywidgets extension for JupyterLab
    # Check this URL for most recent compatibilities
    # https://github.com/jupyter-widgets/ipywidgets/tree/master/packages/jupyterlab-manager
    jupyter labextension install @jupyter-widgets/jupyterlab-manager@^1.0.0 && \
    jupyter labextension install jupyterlab_bokeh@1.0.0 && \
    npm cache clean --force && \
    rm -rf $CONDA_DIR/share/jupyter/lab/staging && \
    rm -rf /home/$NB_USER/.cache/yarn && \
    rm -rf /home/$NB_USER/.node-gyp && \
    fix-permissions $CONDA_DIR && \
    fix-permissions /home/$NB_USER

# Install facets which does not have a pip or conda package at the moment
RUN cd /tmp && \
    git clone https://github.com/PAIR-code/facets.git && \
    cd facets && \
    jupyter nbextension install facets-dist/ --sys-prefix && \
    cd && \
    rm -rf /tmp/facets && \
    fix-permissions $CONDA_DIR && \
    fix-permissions /home/$NB_USER

# Import matplotlib the first time to build the font cache.
ENV XDG_CACHE_HOME /home/$NB_USER/.cache/
RUN MPLBACKEND=Agg python -c "import matplotlib.pyplot" && \
    fix-permissions /home/$NB_USER

USER root

# Install Julia & Julia packages
# Packages are installed in /opt/julia instead of $HOME
ENV JULIA_DEPOT_PATH=/opt/julia
ENV JULIA_PKGDIR=/opt/julia
ENV JULIA_VERSION=1.1.0

RUN mkdir /opt/julia-${JULIA_VERSION} && \
    cd /tmp && \
    wget -q https://julialang-s3.julialang.org/bin/linux/x64/`echo ${JULIA_VERSION} | cut -d. -f 1,2`/julia-${JULIA_VERSION}-linux-x86_64.tar.gz && \
    echo "80cfd013e526b5145ec3254920afd89bb459f1db7a2a3f21849125af20c05471 *julia-${JULIA_VERSION}-linux-x86_64.tar.gz" | sha256sum -c - && \
    tar xzf julia-${JULIA_VERSION}-linux-x86_64.tar.gz -C /opt/julia-${JULIA_VERSION} --strip-components=1 && \
    rm /tmp/julia-${JULIA_VERSION}-linux-x86_64.tar.gz
RUN ln -fs /opt/julia-*/bin/julia /usr/local/bin/julia

# Show Julia where conda libraries are
RUN mkdir /etc/julia && \
    echo "push!(Libdl.DL_LOAD_PATH, \"$CONDA_DIR/lib\")" >> /etc/julia/juliarc.jl && \
    mkdir $JULIA_PKGDIR && \
    chown $NB_USER $JULIA_PKGDIR && \
    fix-permissions $JULIA_PKGDIR

USER $NB_UID

# Add Julia packages
# Juliaのパッケージについても追加で入れたいものがあれば以下2行目の部分に追記して再度ビルドしてください
RUN julia -e 'using Pkg; Pkg.update()' && \
    julia -e "using Pkg; pkg\"add CSV DataFrames Flux IJulia Images InstantiateFromURL JLD Printf Plots PyPlot RDatasets ScikitLearn StatsBase\"; pkg\"precompile\"" && \
    mv $HOME/.local/share/jupyter/kernels/julia* $CONDA_DIR/share/jupyter/kernels/ && \
    chmod -R go+rx $CONDA_DIR/share/jupyter && \
    rm -rf $HOME/.local && \
    fix-permissions $JULIA_PKGDIR $CONDA_DIR/share/jupyter
```

上のDockerfileが用意できたらそのDockerfileがあるディレクトリで

```shell
$ docker build -t jupyter/pyjulia-ml-notebook ./
```

などと打ってもらってDockerイメージをビルドします。なお `jupyter/pyjulia-ml-notebook` という名前は僕が勝手に付けたものなので各自好きに命名してください。その次の `./` でビルド時に参照するDockerfileの置き場所を指定しています。
結構色々入れてるのでそれなりに時間かかりますしWarningもちょいちょい出ますがが気にせず気長に待ちましょう。
ビルドが終わったら次のコマンドでコンテナを立ち上げます。なおJupyter Labを使いたくなければ4行目の`-e JUPYTER_ENABLE_LAB=yes`の部分は不要です。

```shell
$ docker run \
  --rm \
  -p 8888:8888 \
  -e JUPYTER_ENABLE_LAB=yes \
  -e TZ=Asia/Tokyo \
  -v `pwd`:/home/jovyan/work \
  jupyter/pyjulia-ml-notebook:latest
```
起動に成功すれば http://127.0.0.1:8888/lab でJupyterが起動しているのが確認できるはずです。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227776/ce908c77-51ee-35ba-b0ad-acea6c86281c.png" width=800>

また今後このDockerfileで入れたパッケージだけでは足りないものが出てきた場合やパッケージのバージョンを上げたい場合はコード中にも書いているように追加したいパッケージを追記後、再度`docker build -t jupyter/pyjulia-ml-notebook ./` してイメージをビルドすればOKです。

## 参考:
Dockerfileの書き方についてはDocker Hubに上がっている以下2つのイメージを大いに参考にさせていただきました。
- [Docker Hub: jupyter/datascience-notebook](https://hub.docker.com/r/jupyter/datascience-notebook/dockerfile)
- [Docker Hub: jupyter/scipy-notebook](https://hub.docker.com/r/jupyter/scipy-notebook)

というか本当は`jupyter/datascience-notebook`を`docker pull`してくるだけでも最低限のPython/R/Juliaの分析環境は作れるのですが、自分が使わないRのインストール部分を消したかったのと、jupyter/datascience-notebookではTensorflow/Kerasが入っていなかったりJuliaのパッケージが全然入っていなかったりして結局Dockerfileをあれこれ修正するハメになったので今回の記事を書いたというところです。

またJupyterが入った各種のDockerイメージの特徴などはこちらによくまとまっています ➜ [Jupyter Docker Stacks公式](https://jupyter-docker-stacks.readthedocs.io/en/latest/index.html)