DockerでJupyterLab環境を作る

[DockerでPython実行環境を作ってみる](https://qiita.com/jhorikawa_err/items/fb9c03c0982c29c5b6d5)を参考にDockerを色々といじってみたので記事にしました。

この記事のゴールは拡張機能付きでJupyterLab環境を作るところまでです。


# ファイルの内容

まずはJupyterLabを使用するのに最低限必要な内容をみていきます。
フォルダ構成は下記になります。

```:フォルダ構成
Dockerfile
requirements.txt(空テキストファイル)
src(空フォルダでOK)
```

srcはDockerのファイルと同期させてDockerとローカルファイルを
同期させるのに作成しています。

requirements.txtは必要なライブラリを入れておけば、
Docker上でライブラリを使用できるようにしています。


```dockerfile:Dockerfile
FROM python:3

# requirements.txtをDockerファイルへコピー
COPY requirements.txt .
RUN python -m pip install --upgrade pip # pipのアップデート
RUN pip3 install -r requirements.txt # requirements.txtのインストール
RUN pip install jupyterlab # JupyterLabをインストール

WORKDIR /src
COPY /src /src
```

Docker上でrequirement.txtの内容をインストールするために、
コピーする必要があります。

Docker上でrequirmentes.txtを消したい場合はインすロール後に削除コマンドを
入れて記事も見かけました。
削除する場合はインストール後に下記削除コマンドを入れます。

```dockerfile:requirements.txtの削除
rm requirements.txt
```

jupyterlabはpip3でインストールするとエラーになったので、
pipにしています。

Dockerの書き方として`&& \`でつなげて各方法が推奨されていたので、
それを踏まえると下記の方がよさそうです。

```dockerfile:Dockerfile
FROM python:3

COPY requirements.txt .
RUN pip3 install --upgrade pip && \
    pip3 install -r requirements.txt && \
    pip install jupyterlab

WORKDIR /src
COPY /src /src
```

JupyterLabを使用するのに必要なコードは以上です。



# Docker操作

ここからはDockerの操作になります。
まずイメージを作成していきます。

下記のコマンドでイメージを作成しますが、
イメージ名には大文字は使用不可なので注意してください。

```bash:イメージの作成
docker iamge build [-t [イメージ名]:[タグ名] [Dockerfileのあるディレクトリ]]
# 例
docker image build -t jupyterlab_env .
```

イメージが作成されているか確認

```bash
docker image ls
```

イメージが作成されていたらコンテナを作成・立ち上げますが、
やり方が2つあるので順にみていきます。

## JupyterLabの立ち上げ①

一度にコンテナを立ち上げます。

```bash
docker run -v $PWD/src:/src -w /src -it --rm -p 7777:8888 jupyterlab_env jupyter-lab --ip 0.0.0.0 --allow-root 
```

オプションについての説明です。

```docker
# ローカルで作成した内容とコンテナ内で作成した内容が同期する設定
-v

# ワーキングディレクトリの設定
-w

# ポートの設定 [ホストのポート番号:コンテナのポート番号]
-p

# インタラクティブな状態に設定
it

# コンテナ終了時にコンテナを削除
--rm

# JupyterLabの立ち上げ
jupyter-lab --ip 0.0.0.0 --allow-root 
```


ちなみに参考にさせていただいた記事では下記のように`-b`オプションもついてましたが、外してみても動きました。
少し調べてもなぜついていたのかわからなかったのですが、必要なタイミングで見返せるように記載しておきたいと思います。

```bash
docker run -v $PWD/src:/src -w /src -it --rm -p 7777:8888 jupyterlab_env jupyter-lab --ip 0.0.0.0 --allow-root -b localhost
```

コマンドを打って、URLが表示されたら`localhost:7777`にアクセスします。

7777箇所は指定したホストのポート番号なので違う番号にしても問題ないです。
アクセスするとJupyterLabの認証画面が立ちあがります。

下記図のように`token=`で表示されるtokenを入力するとJupyterLabが立ち上がります。


![2021-07-22_18h06_29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428239/c539938e-66e1-a860-8f4d-2a59c589e6d6.png)

終了する場合はターミナル上でCtrl+Cを押すと終了できます。


## JupyterLabの立ち上げ②

上記では直接コンテナを立ち上げましたが、今回はコンテナの中に入ってJupyterLabを立ち上げてみたいと思います。
下記でコンテナを作成します。

```bash
docker run -v $PWD/src:/src -w /src -dit --rm -p 7777:8888 --name JupyterLab jupyterlab_env 
```

先ほどと違う点は2つです。

```docker
# dを加えてバックグラウンドで動くように設定
-dit

# 次でコンテナに入るときにわかりやすいように名前を設定
--name
```

動いているか下記コマンドで確認

```bash
docker ps
```

コンテナの中に入るのに上記で指定したコンテナ名を使用します。

```bash
docker exec -it JupyterLab bash
```

表示が下記のように変わっていたらコンテナの中に入れています。

```
root@852d5b1e5e7c:/src# 
```

これでコンテナないでbash操作ができるので、
pythonのバージョンの確認やpipでのインストールも可能です。

```bash
# pythonのバージョン確認
python --version

# ライブラリのインストール
pip install library
```

JupyterLabを起動させるために下記を入力します。

```bash
jupyter-lab --ip 0.0.0.0 --allow-root
```

--ip、--allow-rootは外したら動かなかったです。


この後の手順は先ほどと同じです。
コンテナの中からは`exit`で出ることができます。

最後にコンテナを削除しておきましょう。

```bash
docker container stop JupyterLab
docker image rm jupyterlab_env
```

今回は実行時に--rmオプションをつけているのでコンテナを停止したら削除されますが、
オプションをつけていない場合は`rm`で削除する必要があるので気を付けてください。

## JupyterLabのオプションについて

[Docker で JupyterLab を起動し、token 入力なしでアクセスする](https://qiita.com/ao_log/items/5438f2aaf5c2b46d2ccb#jupyterlab-%E3%81%AE%E3%82%AA%E3%83%97%E3%82%B7%E3%83%A7%E3%83%B3)で書いてくれていました。
トークンの入力なしでも立ち上げが可能なんですね。

# composeでDocker環境の構築

`docker run`を実施した際につけたオプションを
docker-compose.ymlに記載して立ち上げを楽にします。

フォルダ構成は下記のように変更します。

```bash:フォルダ構成
Dockerfile
requirements.txt(空テキストファイル)
src(空フォルダでOK)
docker-compose.yml #new
```

docker-compose.ymlの内容は下記にします。

```yml:docker-compose.yml
version: '3'
services:
  jupyterlab:
    restart: always
    build:
      context: .
      dockerfile: Dockerfile
    container_name: jupyterlab
    working_dir: '/src'
    tty: true
    volumes:
      - ./src:/src
    ports: 
      - "8080:8080"
    command: jupyter-lab --ip 0.0.0.0 --port=8080 --allow-root --no-browser
```

dockerコマンドは下記です。

```docker
docker compose up
```

今回は8080をポート番号に指定しているので`local:8080`で入ることが可能です。
先ほどはコンテナのポートとホストのポートが違っていたので、
JupyterLabの画面でtokenを入力しました。

しかし、今回はポート番号が同じなのでターミナルで表示されるURL
`http://127.0.0.0:8080/lab_token={発行されたtoken}`
をクリックするだけでtokenも入力されてJupyterLabがたちあがります。