dockerコンテナで複数同時にjupyterを稼働させれば、機械学習用やbot用、webスクレイピング用などと、用途を分けて使用できるので、大変便利です。

また、DB(データベース)専用のコンテナだけ別に用意して、用途に応じて使い分ければ、他プロジェクト等の邪魔にもなりません。

そんなjupyterlabの便利な作業環境の作り方をご紹介です。

なお普通に稼働させるだけなら、anacondaをdockerhubでpullして、次のコマンドを入力すれば1発です。

docker run -i -t -p 8888:8888 continuumio/anaconda3 /bin/bash -c "\
  conda install jupyter -y --quiet && \
  mkdir -p /opt/notebooks && \
  jupyter notebook \
   --notebook-dir=/opt/notebooks --ip='*' --port=8888 \ --no-browser --allow-root"

あっという間に、いま話題の機械学習で人気のpythonを動かすことができます。

ただ、これでは、後から必要なモジュールをインストールしたり、複数同時に管理するのに不向きです。

折角dockerを導入しているなら、最初の環境設定(jupyterのインストール)をしっかり行った方が、後から楽です。

またセキュリティ対策も考慮したうえで、jupyterを導入する事も大事なポイントです。

毎回パスワード入力でログインする、httpsの暗号化された環境で使用すると安全性が高まります。

尚、自分のマシンにdockerをインストールしてlocalhostのpathで使っているなら、それほど気にする必要がないかもしれませんが、レンタルVPS(かごやのレンタルサーバーやconohaなど)を使用しているなら、httpsは、ほぼ絶対条件と考えるべきです。

jupyterはなぜhttps(SSL化)で使うべきなの?

初心者の方でもわかるように簡単に説明しますと、通信される中身がそのままの状態になっているか、暗号化されて解読されにくくなっているかの違いです。

郵便物に例えるなら、http通信がハガキ、https通信が封筒(書留)です。

大袈裟かもしれませんが、httpでのアクセスの場合、通信状態が丸見えの状態になっていると思ってください。jupyterでパスワード情報などを送信しているなら、仮にデータが第3者に覗かれてしまっても、暗号化されてわかりにくい状態になっていた方が安心です。

dockerを使用すれば、コンテナの組み合わせで簡単にhttps(SSL)化が可能です。

もちろん無料で使う事もできます。

ただ、数年前に使用されていた、「nginx-proxy」と「letsencrypt-nginx-proxy-companion」の方法は2022年の時点では利用(imageが存在しないので)できません。

詳しくは、便利になったはずなのに、応用パターンで使用するにはちょっとめんどくさい「docker swag」についてを参考にしてください。

 

 

そこで、新パターンとして、https-potalを利用する方法をご紹介です。

さらにjupyterを利用する時、総合開発環境としてのanacondaを利用するかどうかでも、やり方が違ってきます。

anacondaは色々便利なモジュールが最初からフル装備されているので、機械学習などでpythonを動かすなら大変便利です。

ただ、その分データ容量も増えるのが難点です。

また今回jupyterのhttps化(SSL化)で、ちょっと躓いた部分もあり、試行錯誤した結果、anacondaの有・無バージョンでjupyterを導入したので、2パターンのやり方を記載します。

 

docker-composeでSSL対応のjupyter lab環境を構築(anaconda有)

簡単に違いを説明すると、ディープラーニング等で重宝する機械学習用のモジュールなどがたくさん最初からインストールされているのがanacondaです。

初心者の方では、使用しない機能もたくさんありますが、とにかく何でも揃っているので、後から環境の事をあまり考えないで、作業に専念する事が魅力です。

jupyterlab環境にhttps-potalを使う理由

jupyterlabをhttps(SSL化)で利用するには、認証局によるサーバー証明書が必要になります。

VPSレンタルサーバー会社に有料で発行してもらう事もできますが、 Let’s Encrypt を使用すれば、無料で使えます。

ただし、Let’s Encryptを使って自分で発行する証明書は、有効期限が3ヵ月と短いので、その都度更新する必要があります。

この Let’s Encryptによる証明書の発行と更新の2つの作業を自動化してくれるdockerコンテナになるのが、「https-potal」や「swag」です。

 

以前は、このサーバー認証と更新作業は別々のdockerコンテナで管理するのが主流でした。

先に説明した「jwilder/nginx-proxy」と「jrcs/letsencrypt-nginx-proxy-companion」の組み合わせですが、2022年時点では廃れてしまった古い方法なので、ご注意ください。

サーバー証明書を発行だけするなら「certbot」も便利ですが、1度SSL化のjupyter環境さえ構築してしまえば、ほぼメンテナンスが不要になるhttps-potalが初心者には優しいでしょう。

dockerでjupyterlabとhttps-potalの組み合わせ

dockerによるanacondaとjupyterlabの基本ディレクトリは次のようになります。

jupyter
 ├── docker-compose.yml
 ├──── web
        └──Dockerfile
 ├── workspace
 └── nginx

以上の構成にしておけば、基本のimageをDockerfileに記載しておき、稼働のON、OFFをdocker-compose.ymlに任せる事ができます。

docker-compose.ymlに記載する内容は、2つのコンテナだけで十分です。

version: '3'
services:
        jupyter_web:
                build:
                        context: ./web
                        dockerfile: "Dockerfile"
                image: jupyterlab_anaconda
                container_name: jupyter_web_conda
                user: root
                volumes:
                        - ./workspace:/workspace
                restart: always
                expose:
                          - '8888'
                environment:
                        - PUID=1000
                        - PGID=1000
                networks:
                        - jupyter_net_https_conda

        jupyter_https:
                image: steveltn/https-portal:1
                container_name: jupyter_https_conda
                ports:
                        - '80:80'
                        - '443:443'
                restart: always
                volumes:
                        - ./nginx/ssl_certs:/var/lib/https-portal
                        - ./nginx/conf.d:/etc/nginx/conf.d
                environment:
                        PUID: 1000
                        PGID: 1000
                        DOMAINS: 'mamarutest.com -> http://jupyter_web:8888'
                        WEBSOCKET: "true"
                        STAGE: production
                depends_on:
                        - jupyter_web
                networks:
                        - jupyter_net_https_conda
networks:
        jupyter_net_https_conda:
                driver: bridge
docker-compose.ymlの2つのコンテナ
  • jupyter_web:anacondaにjupyterインストール
  • jupyter_https:https-potal(リバースプロキシ)

jupyter_webコンテナの大事なポイント

build:
   context: ./web
     dockerfile: "Dockerfile"
image: jupyterlab_anaconda

docker-compose buildに対応するため、buildの記載を入れています。

buildによって作成するimage名を指定します

dockerfile: Dockerfileの記載は省略する事も可能ですが、後から見た時に仕組みを思い出しやすいように書いておいた方が無難です。

portsを使わない事で、jupyter_webのコンテナへの直接のアクセスを禁止しています。

 

jupyter_httpsコンテナの大事なポイント

docker hubにあるsteveltn/https-portal:1のイメージをそのまま使用しています。

サーバー証明書の揮発化を防ぐために必要な記述が以下の通りです。

volumes:
    - ./nginx/ssl_certs:/var/lib/https-portal 
    - ./nginx/conf.d:/etc/nginx/conf.d

ホスト側のデータと新規に作成されるjupyter_httpsのコンテナをマウントしておきます。

これで、コンテナが削除されても、サーバー証明書が消える事がなくなります。

 

jupyterのhttps化で最も大事な記述が次です。

environment: 
    DOMAINS: 'mamarutest.com -> http://jupyter_web:8888' 
    WEBSOCKET: "true" 
    STAGE: production

2行目は、コンテナのjupyter_webの8888ポートがmarutest.comに代替えされるという意味です。

矢印のように左から右ではなく、右から左に作用します。

また、WEBSOCKETの記述を忘れると、jupyterが稼働しません。

(wordpress等の通常のWEBサイトなら、WEBSOCKETの記述がなくても動くので、忘れがちです。WEB+httpsと設定が異なります)

さらに、STAGEは3段階に分かれており、local、staging、productionがあります。

STAGEの設定
  • local:localhostなどの自己証明書で使用、他テスト環境でもOK
  • staging:mamarutest.comなどのドメインで使用
  • production:mamarutest.comなど正規のドメインで使用(警告がでなくなる)

最終的にはproducitonでの使用が良いですが、なんども証明書を発行していると使えなくなってしまうので、localやstagingできちんと稼働するのを確認してから切り替えるのが良いでしょう。

またdocker+sorescopeの時にはうまく稼働したワイルドカードDNSのドメインも使えません。

https://crypto-nft-fire.com/docker-serposcope/

サーバー証明書がうまく認識しないようで、jupyterが動きません。

onamae.comなどのキャンペーンを利用すれば、1年間無料でドメインを利用する事が出来るので、ここは必ずドメインを取得しておきましょう。

 

jupyterのhttps(SSL)化で必要なドメイン登録作業

ドメインを取得後、使用するVPS(レンタルサーバー)でドメインの登録作業があります。

1例として、onamae.comでドメイン取得、conohaで登録する場合のやり方をご紹介です。

 

onamae.comでのドメイン登録作業

ドメイン取得後、VPSで利用できるようにネームサーバーの変更をおこないます。

onamae_conoha_dns

今回は、coonhaのVPSで利用するので、conoha用のns-a1.conoha.io、ns-a2.conoha.io、ns-a3.conoha.ioの登録を行います。

conohaのVPSを使う場合のドメイン登録作業

conoha_dns

VPSを利用するconoha側でもドメインを登録する必要があります。

onamae.comで入手したドメインのDNS登録すると、3つのタイプが表示されます。

これにVPSで利用しているIPアドレスを追加、全部の4つのタイプが出来ていれば登録終了です。

dockerでanaconda(jupyter lab)を使う為に必要なDockerfile

docker hubでpullすることが出来るcontinuumio/anaconda3のimageから始めると簡単です。

尚、Dockerfileは、dockerfileでもなく、DockerFileでもなく、必ず最初だけ大文字のDockerfileにしないと認識してくれないので注意です。

FROM continuumio/anaconda3

WORKDIR /workspace
ENV DEBIAN_FRONTEND noninteractive

RUN apt-get update \
    && apt-get install -y sudo wget vim curl gawk make gcc \
    && apt-get clean \
    && rm -r /var/lib/apt/lists/* \
    && ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime

RUN conda install -c conda-forge jupyterlab -y --quiet && \
    conda install nodejs -y && \
    conda install scikit-learn

RUN pip install mplfinance && \
    pip install yahooquery && \
    pip install motor && \
    pip install pybotters


RUN jupyter serverextension enable --py jupyterlab
ENV DEBIAN_FRONTEND dialog

RUN mkdir /workspace && \
        jupyter notebook --generate-config


ENTRYPOINT ["jupyter", "lab", "--ip='*'", "--port=8888", "--no-browser", "--allow-root", "--NotebookApp.allow_origin='*'"]
CMD ["--notebook-dir=/workspace"]

jupyter稼働に必要なnode.jsなどは、anacondaに最初からインストールされていますが、認識しないケースがあったのであえてインストールしています。

その他は、ファイナンス系で必要なモジュールをインストールしています。

Dockerfileで大事な箇所は、ENTRYPOINTです。この記述を間違えただけで、jupyterが稼働しなくなります。

ENTRYPOINT ["jupyter", "lab", "--ip='*'", "--port=8888", "--no-browser", "--allow-root", "--NotebookApp.allow_origin='*'"]

特に、”–NotebookApp.allow_origin=’*'”の記述がないとカーネル認識がないままjupyterが起動するので、コマンド入力の受け付けができません。

不具合解消の正攻法では、jupyterのconfigファイルにc.NotebookApp.allow_origin = ‘*’と記述するのが正解ですが、dockerを使うなら、以上のような使い方もできます。

また、”–LabApp.token=””と記述すれば、パスワードなしでjupyter labを起動する事もできます。

ただ、ドメイン名を知っていれば誰でもアクセスできるので、おすすめできません。(IPテーブルでアクセスできるパソコンを指定するなど、セキュリティを高める方法は、他にもありますが・・・)

VPS(レンタルサーバー)でjupyterを稼働させるならこれで環境構築作業は終了です。

#imageファイルの新規作成 or 更新
$ docker-compose  build 

#jupyterの起動
$ docker-compose up

自己PCで、localhostを利用する場合、この環境構築だけではjupyterlabが動かないケースもあります。その時は、/etc/hostsにtest.localなどのドメイン名を追記すると良いでしょう。

docker-composeのjupyterにDBを連携させる方法

jupyter labを使用していると、DBの管理を別にしたくなるケースもあるでしょう。

そのような時は、もう1つ別にDB付きのjupyter labを立ち上げる方法もあります。

ポイントは、jupyterlab_anacondaで用意したimageの使いまわしです。

jupyter-mongo
 ├── docker-compose.yml
 ├── mongo
       └── Dockerfile
 ├── workspace
 └── nginx

完全に別のjupyterlabにするなら、jupyter_webのimageも別にした方が良いですが、DBを追加するだけなので、あえて同じにしています。

尚、docker-compose.ymlとDockerfileの組み合わせで何度もbuildとupを行う場合、imageも別にするのが、正しい運用方法です。

version: '3'
services:
        jupyter_web:
                image: jupyterlab_anaconda
                container_name: jupyter_web_mongo
                user: root
                volumes:
                        - ./workspace:/workspace
                        - ./mongo_jupyter/data:/home/work
                restart: always
                expose:
                        - '8888'
                environment:
                        - PUID=1000
                        - PGID=1000
                depends_on:
                        - mongodb
                networks:
                        - jupyter_net_mongo
        mongodb:
                build:
                        context: ./mongo
                        dockerfile: "Dockerfile"
                image: mongodb_compass
                container_name: mongodb
                volumes:
                        - ./mongo/mongo-data:/data/db
                        - ./mongo/mongodb-configdb:/data/configdb
                ports:
                        - '27017:27017'
        jupyter_https:
                image: steveltn/https-portal:1
                container_name: jupyter_https_mongo
                ports:
                        - '2980:80'
                        - '29443:443'
                restart: always
                volumes:
                        - ./nginx/ssl_certs:/var/lib/https-portal
                        - ./nginx/conf.d:/etc/nginx/conf.d
                environment:
                        PUID: 1000
                        PGID: 1000
                        DOMAINS: 'marumaru-test.com -> http://jupyter_web:8888'
                        WEBSOCKET: "true"
                        STAGE: local
                depends_on:
                        - jupyter_web
                networks:
                        - jupyter_net_mongo

networks:
        jupyter_net_mongo:
                driver: bridge

mongoDBという、DB専用のコンテナを追加しています。

また、jupyter labを複数稼働させるために、ホストに繋がるポートは別に変更しています。

尚、使用するポートが異なるので、同じDNS(DOMAINSに記載するドメイン)を使っても大丈夫です。

mongoDB用のDockerfile、そのままmongoのimageを使ってもOKですが、タイムを日本時間に変更するなど、buildで多少の変更は加えておいた方が良いでしょう。

FROM mongo
RUN apt-get update \
    && apt-get install -y sudo wget vim curl gawk make gcc \
    && apt-get clean \
    && rm -r /var/lib/apt/lists/* \
    && ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime

jupyterで作ったDBは、MongoDB Compassで確認すると視覚的にもわかりやすいので、おすすめです。

ややこしいですが、MongoDB Compassのソフトは、自宅のPCにインストールして、CompassからVPSサーバにアクセスする流れになります。

docker-composeでSSL対応のjupyter lab環境を構築(シンプル構成)

python初心者の方がお勉強で使用する程度なら、anacondaなしでも十分問題なく使用できます。

シンプル構成なので、何か問題があった時、問題の切り分け等が簡単です。

基本はanaconda付きのjupyter labとほぼ同じです。docker-compose.ymlファイルなど、jupyter_webのimage以外全部一緒でもOKです。

ただ、複数同時に稼働させるために、コンテナ名だけ別にしておいた方が良いでしょう。

違いは、Dockerfileです。

 

シンプルな反面、必要なpythonモジュールを全部自分でインストールしなければなりません。

FROM python:3
USER root
WORKDIR /workspace
ENV DEBIAN_FRONTEND noninteractive

# 必要なパッケージを記載
RUN apt-get update && apt-get install --no-install-recommends -y \
curl && \
apt-get clean

# 必要なPythonモジュールを記載
RUN python -m pip install --upgrade pip && pip install \
numpy \
scipy \
matplotlib \
ipython \
scikit-learn \
pandas \
pillow \
mglearn \
requests \
pyperclip \
beautifulsoup4 \
motor \
pybotters \
jupyterlab

RUN jupyter serverextension enable --py jupyterlab
ENV DEBIAN_FRONTEND dialog

RUN mkdir /workspace && \
jupyter notebook --generate-config

ENTRYPOINT ["jupyter", "lab", "--ip='*'", "--port=8888", "--no-browser", "--allow-root", "--NotebookApp.allow_origin='*'"]
CMD ["--notebook-dir=/workspace"]

必要なモジュールを追加して、docker-compose build、その後docker-compose upの繰り返しなので、慣れてくるとかなり楽です。

anacondaバージョンに比べて、挙動がおかしくなる確率も格段に低いです。

尚、docker image psで確認すると、anacondaのイメージは約3.8GB、jupyter単独は約1.8GBと2GBの差があります。

docker+https-potal+jupyterをレンタルサーバー(VPS)で構築する時の注意

最後にjupyterのhttps化ではまった箇所のご紹介です。

https化さえしなければ、初心者でもdockerを使えば10分ほどで環境構築が可能ですが、はまると何時間も環境構築に時間がかかるので、dockerの仕組みをしっかり理解してから、docker-composeを使いましょう。

dockerの意味があまりないかも知れませんが、dockerコンテナを1つ作ったらその中で全てのソフト等をインストールするというのも1つの方法です。

jupyter_webのカーネルが認識しない

jupyterlabがブラウザで立ち上がっても、pythonコマンド等が認識しない場合があります。

そのような時は、おそらく次のいずれかに原因があります。

 

ドメインを登録したばかりでドメインが認識しない!

DNS登録して1時間ぐらいでドメインは使えるようになりますが、SSLで認識するのにはさらに時間がかかります。

Let’s Encryptでサーバー証明書を発行してから24時間ぐらいは、気長に待ちましょう。

A.comで使用できるけど、B.comでは使えないという場合は、ドメインの可能性が高いです。

ファイヤーウォールでポート許可がOKになっていない!

ファイヤーウォールのポートが開いていなかったというポンミスもあるので、ご注意ください。

デフォルト443のポートは開いているケースが多いですが、複数のjupyter labを起動する時はポートを変更する必要があります。その時、対象のポートが開いているのか、確認も大事です。

$ ufw status

ポートの解放、10443を開放する場合

$ ufw allow 10443

ファイヤーウォールの再起動

$ ufw reload

jupyterの起動設定のセキュリティが高すぎる!

dockerのログを確認すると、Blocking Cross Origin API request などといった、Cross Origin系の問題が表示される場合、chromブラウザ等のセキュリティチェックに引っかかっている可能性があります。

これは、dockerの問題と言うより、jupyter側の設定の問題です。

環境ファイルconfigに次の記述を加えるだけで解決するケースが多いです。

c.NotebookApp.allow_origin='*'

尚、私の場合、Dockerfileに記述して、対策しています。

node.jsファイルがインストールされていない

jupyterの起動には、node.jsが必須です。

次のようなログがあった場合は、node.jsを疑ってみてください。

Could not determine jupyterlab build status without nodejs

インストールタイミングで壊れてしまった場合などは、再インストールで解消するとの報告などもよく見かけますが、これで解決したことはありません。

ドメインが機能していない場合も同じようなエラーログが表示されます。

色々インストールしすぎると、jupyter再起動後に認識しなくなるケースもあるので、imageコンテナのバージョン管理はしっかりおこないましょう。

以上 環境構築さえしっかりできれば、非常に便利なjupyter labですが、問題の切り分けに失敗すると深みにはまるので、ご注意です。

 

docker+jupyterをパスワード付きで運用できるようにする方法

Dockerfileに記述ずみです。そのままコピペすれば、最初だけ、トークンを入力し、その後はパスワード運用ができるようになります。