Dockerでデータサイエンス環境構築

# 環境
OS: macOS Big Sur 11.1
Docker: 20.10.0
docker-compose: 1.27.4

# 注意点

コマンドの実行は管理者権限で行なってください。また、Docker、docker-composeはすでにインストールされているものとして進めていきます。

Docker imageはDockerfileを基に構築されます。Docker imageを一度`build`した際はキャッシュが作成されます。キャッシュとは簡単に言えば、2回目以降の読込を高速化するものです。このキャッシュがあると、`build`の際に優先的に用いられてしまいます。そのため、Dockerfileを更新した際は`docker-compose build --no-cache`でキャッシュを使用しない`build`をしましょう。

キャッシュを使用しない`build`ですので、ものによってはかなり時間が掛かることもありますので、ご注意ください。

# Dockerとは

Dockerとは、簡単にいえば仮想マシンのようなものです。ただ厳密には異なり、サーバーのカーネルを利用してプロセスやユーザーをサーバーごとに隔離し、あたかも別のマシンが動いているように動かすことができます。そのため、仮想化よりも軽量で高速に動きます。Dockerを使用することで簡単に環境構築をすることができ、OSの違いを考慮することなく簡単に自分の環境を共有できます。

# 事前準備

[注意点](#注意点)にも記載していますが、すでにDocker、docker-composeはインストールされているものとします。その上で、ターミナル上で以下のコマンドを打ち込みます。

```terminal
$ docker pull jupyter/datascience-notebook:latest
```

このコマンドで、DockerイメージをDocker Hubからローカルに引っ張ってきます。このとき使用するDockerイメージが決まっていれば、ご自分のお好きなものを選択しても良いです。Dockerイメージの選択にはJupyterの[公式サイト](https://jupyter-docker-stacks.readthedocs.io/en/latest/using/selecting.html#jupyter-datascience-notebook)をご確認いただき、選択してみてください。迷ったら上記の`datascience-notebook`を使用すれば大丈夫です。

この段階で、ご自分のJupyterにパスワードを設定することが可能です。ローカルの環境でのみ作業をする場合は特に設定する必要はありませんが、もし必要であれば[コチラ](https://qiita.com/y4m3/items/c2703d4e131e05084b7b)の記事が分かりやすかったので、参考にしてみてください。

その後、ご自分の任意のディレクトリに以下の[Dockerfile](#dockerfile)を保存してください。

# Dockerfile

```Dockerfile
FROM jupyter/datascience-notebook

RUN pip install --upgrade pip
RUN pip install jupyterlab
RUN jupyter serverextension enable --py jupyterlab

### Jupyterlab 拡張機能
# Variable Inspector
RUN jupyter labextension install @lckr/jupyterlab_variableinspector
# Table of Contents
RUN jupyter labextension install @jupyterlab/toc

### settings
## prepare settings ※ ここのディレクトリはjupyterlabのSettingsのAdvanced Setting Editorを参照する
RUN mkdir -p /home/jovyan/.jupyter/lab/user-settings/@jupyterlab/apputils-extension
RUN mkdir -p /home/jovyan/.jupyter/lab/user-settings/@jupyterlab/notebook-extension
## user-settings ※ prepare settingsでディレクトリを生成していないとerror
# 黒背景
RUN echo '{"theme":"JupyterLab Dark"}' > \
  /home/jovyan/.jupyter/lab/user-settings/@jupyterlab/apputils-extension/themes.jupyterlab-settings
# 行番号表示
RUN echo '{"codeCellConfig": {"lineNumbers": true}}' > \
  /home/jovyan/.jupyter/lab/user-settings/@jupyterlab/notebook-extension/tracker.jupyterlab-settings
```

詳しく中身について解説はしませんが、この[Dockerfile](#dockerfile)でデータサイエンス環境Jupyterlabの設定を行なっています。コメント文を読めば何の目的に書いたコマンドなのかが分かるかと思いますので、興味のある方はぜひ詳しく見てみてください。

特に`setting`以下はコマンドとして記載しておくことで、デフォルトのJupyterlabを黒背景、そして行番号を表示してくれるようになるので、個人的には記載必須です。

次にdocker-composeです。

# docker-compose とは

docker-composeは、複数のコンテナで構成されるアプリケーションについて、Dockerイメージのビルドや各コンテナの起動・停止などをより簡単に行えるようにするものです。

# docker-compose.yml

```docker-compose
version: "3"
services:
  jupyterlab:
    build:
      context: .
      dockerfile: "Dockerfile"
    user: root
    container_name: con_jupyterlab
    image: jupyterlab
    ports:
      - "8888:8888"
    volumes:
      - "/Users/[user]/Documents/DataScience/jupyter:/home/jovyan/work"
    environment:
      GRANT_SUDO: "yes"
      TZ: Asia/Tokyo
    command: start.sh jupyter lab --NotebookApp.token=""
```

こちらについても詳しい解説はしません。適宜Dockerイメージ名、コンテナ名はご自身で作成したものを記載してください。`volumes`については、コロン（：）前までのパスは、ご自身のDockerfileの存在するパスを指定してください。この部分が間違っていると、コンテナを停止する度にデータサイエンス環境で作業した内容が消去されてしまいます。必ず作業を行う前にデータが保持されているかの確認を忘れないようにしておいてください。

# 使用方法

ターミナルの`cd`コマンドを用いて、Dockerfile(docker-compose.yml)が存在しているディレクトリまで移動します。そこで、下記コマンドを実行します。

```terminal
$ docker-compose up -d
```

実行した後、少々待ったら http://localhost:8888 にアクセスします。このような画面になっていたら成功です。

![jupyterlab.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674330/9022fe69-9de2-3311-77ac-fa6a16aff7c4.png)

もし「ページを開けませんでした」とか「サーバに接続できません」と出たら、少し時間を開けた後に再度ページリロードを行なってみてください。それでもダメな場合はDockerfileかdocker-composeに間違いがありますので、ターミナル上のエラーメッセージを確認してみてください。

エラーが出ていなかったら、以上で作業は終わりです。お疲れさまでした。

# Pythonの日本語対応化

初期状態のPythonは日本語に対応していません。日本語をそのまま表示させようとすると、いわゆる豆腐文字（文字化け）になってしまいます。フォントを導入し、日本語を表示できるようにします。詳しくは[コチラ](https://qiita.com/e4Rl97/items/2b940b4354670ead3eb9)の記事を参考にしてください。

# おわりに

Dockerというものは、自分の環境を汚すことなく、開発環境を構築することができ、他人にも自分の環境を共有することが可能になります。これによって、環境による開発者同士の齟齬が起きなくなります。他にも軽量で高速といった特徴があるので、ぜひ勉強してみてください。