Docker+Pipfileを使ったJupyter Lab環境の作り方

この記事ではdocker-compose.ymlとPipfileを使って仮想環境上でのJupyter Lab環境を簡単に作る方法を解説します。
対象の方としてはとりあえず、テンプレとしてJupyter Labの環境の作りかたが欲しい方、Dockerの使い方の応用をしたい方向けになります。

基本的なDockerの使い方としては以前に書いた記事で[Dockerの基本的な使い方](https://qiita.com/kitanotamayura/items/b240eb850514f3ad2381)を参考にしてください。
また、docker-composeに関しては[初めてのdocker-compose](https://qiita.com/kitanotamayura/items/39a8a759463790412117)があるので参考にしていただけると嬉しいです。



## 環境

- MacBook Air (Retina, 13-inch, 2020)
- Docker version 20.10.7
- docker-compose version 1.29.2

## 作るもの

以下のようなDocker上でJupyter Labの環境

- docker-composeを使った一つのコマンドで作れる環境
- Pipfileでライブラリのバージョン管理

## ディレクトリ構成

まず、ディレクトリを以下の図のように作ります。
ここで、各ファイルやディレクトリの内容説明します。
codeの中にはvolumeによってコンテナ内とコンテナ外がリアルタイムで反映されるディレクトリになります。ここではsample.ipynbを作っています。コンテナ内でのファイルの変更や作成がここにリアルタイムで反映されます。
Dockerfileによってコンテナ内の環境を作る設計図になります。
Pipfileにはコンテナ内に入れたいライブラリなどをバージョンとセット書いておきます。
docker-compose.ymlにはportの接続やvolumeの接続などのDockerファイルからDockerコンテナの作成までを一つのコマンドで実行するための設計図です。


root/
┣ code/
┃　┗ sample.ipynb
┣ Dockerfile
┣ Pipfile
┗ docker-compose.yml







## Dockerfile

ここではDockerfileについて説明します。基本的なDockerfileのコマンドについては[Dockerの基本的な使い方](https://qiita.com/kitanotamayura/items/b240eb850514f3ad2381)に書いてありますので参考にしていただけると幸いです。

- ベースとなるイメージとしてubuntuを指定
- sudo/wget/curl/vimのインストール
- ワーキングディレクトリに/optに移動
- anacondaのインストール
- anacondaのPATHを通す
- pipのupgrade
- pipenvのインストール
    - これはPipfileを使ったライブラリのインストールに使います
- Pipfileのコピー
    - コンテナ内でライブラリをインストールをするときに使うPipfileをコンテナ内にコピーします
- pipenvを使ってPipfileに書いてあるライブラリをインストール
- ワーキングディレクトリの変更をroot(/)に移動
- jupyter labの実行


```dockerfile
FROM ubuntu:18.04

RUN apt-get update && apt-get install -y \
    sudo \
    wget \
    curl \
    vim

WORKDIR /opt

# anacondaのダウンロードとインストール
RUN wget https://repo.anaconda.com/archive/Anaconda3-2019.10-Linux-x86_64.sh && \
    sh /opt/Anaconda3-2019.10-Linux-x86_64.sh -b -p opt/anaconda3 && \
    rm -f Anaconda3-2019.10-Linux-x86_64.sh

# anacondaのPATHを通す
ENV PATH /opt/opt/anaconda3/bin:$PATH

# pipのupgrade
RUN pip install --upgrade pip

# pipenvのインストール
RUN pip install pipenv

# Pipfileなどをコンテナ内にコピー
COPY . /

# pipenvを使ってPipfileに書いてあるライブラリをインストール
RUN pipenv install --skip-lock

# pytorchをインストール
RUN pip install torch==1.9.1+cpu torchvision==0.10.1+cpu torchaudio==0.9.1 -f https://download.pytorch.org/whl/torch_stable.html

# ワーキングディレクトリの変更
WORKDIR /

# jupyter labの実行
CMD ["jupyter", "lab", "--ip=0.0.0.0", "--allow-root", "--LapApp.token=''"]
```

## Pipfile

Pipfileの書き方を説明します。
Pipfileを書くことは簡単で初めに`[packages]`を書いて、その下にインストールしたいライブラリとバージョンを書くだけです。実際には他にもいくつかの機能などがありますが今回はこれだけで十分です。

テンプレとしてこのコードを使うときにはここに追加したいライブラリを入れて使ってください。


```pipfile
[packages]
numpy = "==1.18.4"
Pillow = "==6.2.1"
jupyterlab = "2.2.9"
```

## docker-compose.yml

ここではdocker-compose.ymlの書き方を説明します。

まずversionでdocker-compose.ymlのファイルフォーマットのバージョンを宣言しています。
次に、service以下で具体的なコンテナについての設定を書いていきます。ここでは作成、実行するコンテナはひとつだけですが、使い方によっては複数のコンテナを作成することができます。
echoはコンテナの名前です。


`build: .`はdocker-compose.ymlと同じpathにあるDockerfileからDockerイメージ・コンテナの作成をします。ここで、Dockerfileの名前を"Dockerfile"以外したときにはここにpathと名前を書く必要があります。

`ports: - 8889:8888`はコンテナの内外のポート番号を合わせることに使います。コンテナ内のポート番号8888とコンテナ外のポート番号8889を対応させています。これはコンテナ内でjupyter labを開いたときに外部からコンテナ内のポート番号に接続するために使います。
`volumes: - ./code:/code`これはコンテナの外部の`./code`以下のコードがコンテナの内部の`/code`以下と対応させています。

```docker-compose.yml
version: "3"
services:
  echo:
    build: .
    ports:
      - 8889:8888
    volumes:
      - ./code:/code
```

## 実際に環境を作成してみる

ファイルを作ってきたのでここでは実際にjupyter labの環境を作っていきます。
docker-compose.ymlがあるディレクトリで

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

を実行する。すると以下のように表示される。実際に実行してみるとxxxxxxxxxxxxxxxxxにはtokenが表示されます。このtokenは後で利用します。

```terminal
Starting sample_notebook_env_echo_1 ... done
Attaching to sample_notebook_env_echo_1
echo_1  | [I 17:04:29.653 LabApp] JupyterLab extension loaded from /opt/opt/anaconda3/lib/python3.7/site-packages/jupyterlab
echo_1  | [I 17:04:29.653 LabApp] JupyterLab application directory is /opt/opt/anaconda3/share/jupyter/lab
echo_1  | [I 17:04:29.656 LabApp] Serving notebooks from local directory: /
echo_1  | [I 17:04:29.656 LabApp] The Jupyter Notebook is running at:
echo_1  | [I 17:04:29.656 LabApp] http://83d510b77e7b:8888/?token=xxxxxxxxxxxxxxxxxxxxxxxxxx
echo_1  | [I 17:04:29.656 LabApp]  or http://127.0.0.1:8888/?token=xxxxxxxxxxxxxxxxxxxxxxxxxx
echo_1  | [I 17:04:29.656 LabApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).
echo_1  | [W 17:04:29.660 LabApp] No web browser found: could not locate runnable browser.
echo_1  | [C 17:04:29.660 LabApp]
echo_1  |
echo_1  |     To access the notebook, open this file in a browser:
echo_1  |         file:///root/.local/share/jupyter/runtime/nbserver-1-open.html
echo_1  |     Or copy and paste one of these URLs:
echo_1  |         http://83d510b77e7b:8888/?token=xxxxxxxxxxxxxxxxxxxxxxxxxx
echo_1  |      or http://127.0.0.1:8888/?token=xxxxxxxxxxxxxxxxxxxxxxxxxxx
```



ブラウザで`http://localhost:8889/`を開くと![スクリーンショット 2021-11-19 2.14.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/305234/2d40fbe6-ff8f-540a-cdb4-ce9b465b1d51.png)

が開かれます。

# 終わりに

ここでは簡単なDocker環境上でのJupyter Labの作り方を紹介してみました。
こちらをテンプレとして少しずつ書き換えていくと自分の欲しい環境を自在に作れるようになるのではないかと思います。

質問、コメント、間違っていることろなどがありましたら、コメントをいただけると嬉しいです。