Docker-compose で https 対応の Jupyter lab を作る

Python の勉強をするついでに HTTPS 対応した Jupyter lab を Conoha VPS@CentOS 7 で建ててみました。
メモ代わりにまとめてみました。

大変参考にさせていただきました。
[JupyterLab を Docker + nginx-proxy で構築する](https://blog.itdog.jp/entry/2018/02/18/jupyterlab-docker-nginx-proxy/)
[docker-composeでLet's Encrypt SSL,HTTP2通信対応Nginxリバースプロキシサーバを構築する](http://peeeeron.hatenablog.com/entry/2017/10/31/144658)

1. 構築環境
-
- ConoHa VPS@CentOS 7
- docker 18.06.1-ce
- docker-compose 1.21.2, build a133471
- jupyter.example.com へホスティングする

2. ディレクトリ構成
-
ファイル構成は下図のように配置しました。
>/home/jupyter/
>　┣ docker-nginx/
>　┃　┗ docker-compose.yml
>　┗ docker-jupyterlab/
>　　　┗ docker-compose.yml

3. nginx-proxy, letsencrypt-nginx-proxy-companion の作成 
-
```yml:docker-nginx/docker-compose.yml
version: '2'
services:
  nginx-proxy:
    image: jwilder/nginx-proxy
    container_name: nginx-proxy
    privileged: true
    ports:
      - 80:80
      - 443:443
    volumes:
      - ./docker-compose.d/certs:/etc/nginx/certs:ro
      - ./docker-compose.d/htpasswd:/etc/nginx/htpasswd
      - /etc/nginx/vhost.d
      - /usr/share/nginx/html
      - /var/run/docker.sock:/tmp/docker.sock:ro
    restart: always

  letsencrypt-nginx:
    image: jrcs/letsencrypt-nginx-proxy-companion
    container_name: letsencrypt-nginx
    privileged: true
    volumes:
      - ./docker-compose.d/certs:/etc/nginx/certs:rw
      - /var/run/docker.sock:/var/run/docker.sock:ro
    volumes_from:
      - nginx-proxy
    restart: always

networks:
  default:
    external:
      name: webproxy
```

次にネットワークの作成を行います。

```bash
$ docker network create webproxy
```
無事にできたらコンテナを起動してみます。

```bash
$ docker-compose up -d
```
この状態で example.com へアクセスすると 503 Error ページが表示されます。

4. Jupyter lab の作成
-
ひとまず起動できるか確認したいので、 `--NotebookApp.token=''` にしておきます。

```yml:docker-jupyterlab/docker-compose.yml
version: '2'

services:
  jupyterlab:
    image: jupyter/tensorflow-notebook:latest
    user: root
    environment:
      NB_UID: 1000
      NB_GID: 100
      GRANT_SUDO: "yes"
      VIRTUAL_HOST: jupyter.example.com
      LETSENCRYPT_HOST: jupyter.example.com
      LETSENCRYPT_EMAIL: hoge@example.com
      LETSENCRYPT_TEST: "false"
    volumes:
       - "./work:/home/jovyan/work"
    privileged: true
    expose:
      - "8888"
    restart: unless-stopped
    command: start.sh jupyter lab --NotebookApp.token=''
networks:
  default:
    external:
      name: webproxy
```

また、下記部分は自分の環境に変更するようにしてください。

```yml
      VIRTUAL_HOST: jupyter.example.com
      LETSENCRYPT_HOST: jupyter.example.com
      LETSENCRYPT_EMAIL: hoge@example.com
```


コンテナを起動してみます。

```bash
$ docker-compose up -d
```

起動後しばらくまった後に jupyer.example.com に接続ます。
SSL認証マークがついたら無事完了です！嬉しい！

5. パスワードの設定
-
このままだと jupyter.example.com へ接続すると誰でも接続できてしまうので、パスワードを設定します。
Console で iPython で passwd() 用いてパスワードのハッシュ値を生成します。

Jupyter lab の Launcher から Terminal を選択後、 `ipython` と入力することで iPython の Console に入ることができます。
<img width="753" alt="launcher.png" src="https://qiita-image-store.s3.amazonaws.com/0/277121/bd08d944-ac15-f707-2a25-c4413b783886.png">

```bash
jovyan@[ContainerID]:~$ ipython
```
iPython の Console で下記のように実行し、設定したいパスワードを 2 回入力し、
出力されたハッシュ値をメモします。

```py
In [1]: from notebook.auth import passwd

In [2]: passwd()
Enter password:
Verify password:
Out[2]: 'sha1:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
```
Jupyter lab のコンテナを停止させておきます。

```bash
$ docker-compose stop
```
`docker-jupyterlab/docker-compose.yml` の command 部を下記のように変更します。

```bash
command: start.sh jupyter lab --NotebookApp.token=''
↓
command: start.sh jupyter lab --NotebookApp.password='sha1:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
```
変更後の docker-jupyterlab/docker-compose.yml がこちら。

```yml:docker-jupyterlab/docker-compose.yml
version: '2'

services:
  jupyterlab:
    image: jupyter/tensorflow-notebook:latest
    user: root
    environment:
      NB_UID: 1000
      NB_GID: 100
      GRANT_SUDO: "yes"
      VIRTUAL_HOST: jupyter.example.com
      LETSENCRYPT_HOST: jupyter.example.com
      LETSENCRYPT_EMAIL: hoge@example.com
      LETSENCRYPT_TEST: "false"
    volumes:
       - "./work:/home/jovyan/work"
    privileged: true
    expose:
      - "8888"
    restart: unless-stopped
    command: start.sh jupyter lab --NotebookApp.password='sha1:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
networks:
  default:
    external:
      name: webproxy
```

編集後起動します。

```bash
$ docker-compose up -d
```

これでパスワード画面が表示されたら完了です！お疲れ様でした。
<img width="321" alt="jupyter_login.png" src="https://qiita-image-store.s3.amazonaws.com/0/277121/d8e8f63f-6459-2928-eb79-e61d7c5c1cf1.png">

よい Python ライフを！