今回のエントリは、以下のエントリの改訂版となる。 起動するアプリケーションを Jupyter Notebook から JupyterLab にすると共に、いくつか変更を加えた。
JupyterLab は従来の Jupyter Notebook を置き換えることを目的とした後継プロジェクト。 基本的な部分は Notebook を受け継ぎつつも、より扱いやすいインターフェースを提供している。
今回使う環境は次の通り。
$ cat /etc/lsb-release DISTRIB_ID=Ubuntu DISTRIB_RELEASE=18.04 DISTRIB_CODENAME=bionic DISTRIB_DESCRIPTION="Ubuntu 18.04.3 LTS" $ uname -r 4.15.0-62-generic
Docker をインストールする
まずはリポジトリを更新すると共に、過去にインストールした Docker 関連コンポーネントがあれば削除しておく。
$ sudo apt update $ sudo apt -y remove docker docker-engine docker.io containerd runc
Docker のインストール用リポジトリを APT に登録する。
$ sudo apt -y install \ apt-transport-https \ ca-certificates \ curl \ gnupg-agent \ software-properties-common \ python3-pip $ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - $ sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" $ sudo apt update
Docker の主要コンポーネントをインストールする。
$ sudo apt -y install docker-ce docker-ce-cli containerd.io $ sudo docker version Client: Docker Engine - Community Version: 19.03.2 API version: 1.40 Go version: go1.12.8 Git commit: 6a30dfc Built: Thu Aug 29 05:29:11 2019 OS/Arch: linux/amd64 Experimental: false Server: Docker Engine - Community Engine: Version: 19.03.2 API version: 1.40 (minimum version 1.12) Go version: go1.12.8 Git commit: 6a30dfc Built: Thu Aug 29 05:27:45 2019 OS/Arch: linux/amd64 Experimental: false containerd: Version: 1.2.6 GitCommit: 894b81a4b802e4eb2a91d1ce216b8817763c29fb runc: Version: 1.0.0-rc8 GitCommit: 425e105d5a03fabd737a126ad93d62a9eeede87f docker-init: Version: 0.18.0 GitCommit: fec3683
ついでに Docker Compose もインストールしておく。
$ sudo pip3 install docker-compose $ docker-compose version docker-compose version 1.24.1, build 4667896 docker-py version: 3.7.3 CPython version: 3.6.8 OpenSSL version: OpenSSL 1.1.1 11 Sep 2018
JupyterLab を起動するイメージを用意する
今回はデーモンを Supervisord 経由で起動することにした。
JupyterLab だけを起動するなら別に直接起動してもいいんだけど、拡張性などを考えて。
%%
で囲まれている部分は後で環境変数経由で置き換える。
$ cat << 'EOF' > supervisord.conf [supervisord] nodaemon=true [program:jupyterlab] command=%%CONDA_HOME%%/envs/%%CONDA_VENV_NAME%%/bin/jupyter-lab user=%%USERNAME%% stdout_logfile=/var/log/supervisor/jupyter-lab.log redirect_stderr=true autostart=True autorestart=True EOF
続いて Supervisord を起動するエントリーポイントとなるシェルスクリプト。 この中では主に設定ファイルの準備をしている。 JupyterLab の Web UI にトークンなしでアクセスできるようにするなど。 JupyterLab の Web UI には SSH Port Forwarding 経由でアクセスするため、アクセス制御については SSH の部分で担保する。
$ cat << 'EOF' > docker-entrypoint.sh #!/usr/bin/env bash set -Ceux : "Set home directory" && { export HOME=/home/${USERNAME} } : "Replace template variables" && { sed -i.back \ -e "s:%%USERNAME%%:${USERNAME}:g" \ -e "s:%%CONDA_HOME%%:${CONDA_HOME}:g" \ -e "s:%%CONDA_VENV_NAME%%:${CONDA_VENV_NAME}:g" \ /etc/supervisord.conf } : "Jupyter configuration" && { if [ ! -e /home/${USERNAME}/.jupyter ]; then sudo -iu ${USERNAME} ${CONDA_HOME}/envs/${CONDA_VENV_NAME}/bin/jupyter notebook --generate-config sudo -iu ${USERNAME} sed -i.back \ -e "s:^#c.NotebookApp.token = .*$:c.NotebookApp.token = u'':" \ -e "s:^#c.NotebookApp.ip = .*$:c.NotebookApp.ip = '*':" \ -e "s:^#c.NotebookApp.open_browser = .*$:c.NotebookApp.open_browser = False:" \ -e "s:^#c.NotebookApp.notebook_dir = .*$:c.NotebookApp.notebook_dir = \"${JUPYTER_HOME}\":" \ /home/${USERNAME}/.jupyter/jupyter_notebook_config.py fi } : "Start supervisord" && { supervisord -c /etc/supervisord.conf } EOF
インストールしたい Python のパッケージの一覧を書いておくファイル。
$ cat << 'EOF' > requirements.txt jupyterlab EOF
続いては、肝心の Dockerfile となる。
Python の実行環境については Miniconda でやってしまうことにした。
インストール先や仮想環境は CONDA_HOME
と CONDA_VENV_NAME
で変更できる。
$ cat << 'EOF' > Dockerfile FROM ubuntu:18.04 ENV CONDA_HOME=/opt/conda \ CONDA_VENV_NAME=venv \ JUPYTER_HOME=/mnt/jupyter # Use mirror repository RUN sed -i.bak -e "s%http://[^ ]\+%mirror://mirrors.ubuntu.com/mirrors.txt%g" /etc/apt/sources.list # Install prerequisite packages RUN apt update \ && apt -yq dist-upgrade \ && apt install -yq --no-install-recommends \ sudo \ supervisor \ ca-certificates \ wget # Install miniconda RUN wget --quiet https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda3.sh \ && /bin/bash /tmp/miniconda3.sh -b -p ${CONDA_HOME} \ && rm /tmp/miniconda3.sh \ && ${CONDA_HOME}/bin/conda clean -tipsy \ && ln -s ${CONDA_HOME}/etc/profile.d/conda.sh /etc/profile.d/ # Create virtual environment COPY requirements.txt /tmp RUN . /etc/profile.d/conda.sh \ && conda create -y -n ${CONDA_VENV_NAME} python=3.7 \ && conda activate ${CONDA_VENV_NAME} \ && pip install -r /tmp/requirements.txt # Expose container ports EXPOSE 8888 # Boot process COPY supervisord.conf /etc COPY docker-entrypoint.sh /var/tmp CMD bash /var/tmp/docker-entrypoint.sh EOF
起動するときのオプションがなるべく増えないように Docker Compose の設定ファイルも作っておく。
以下では docker-compose.yml
のあるディレクトリを JupyterLab の作業ディレクトリとして /mnt/jupyter
にマウントしている。
必要に応じて場所は書き換えると良いと思う。
$ cat << 'EOF' > docker-compose.yml version: "3" services: jupyter-lab: build: context: . environment: - USERNAME - JUPYTER_HOME=/mnt/jupyter image: example/jupyterlab-container volumes: - /etc/passwd:/etc/passwd:ro - /etc/group:/etc/group:ro - /home:/home - ./:/mnt/jupyter ports: - "127.0.0.1:8888:8888" EOF
また、パーミッション問題を避けるために上記では /etc/passwd
と /etc/group
をコンテナにマウントしてしまっている。
このテクニックについては以下を参照のこと。
準備ができたらイメージをビルドする。
$ sudo docker-compose build
コンテナを起動する
コンテナを起動する前に、念のため SSH に使うポート以外をファイアウォールで閉じておく。 コンテナが bind するアドレスはループバックアドレスなのでインターネットには晒されないけど念のため。
$ sudo ufw allow 22 $ sudo ufw default DENY $ yes | sudo ufw enable $ sudo ufw status Status: active To Action From -- ------ ---- 22 ALLOW Anywhere 22 (v6) ALLOW Anywhere (v6)
JupyterLab のコンテナを起動する。
$ sudo docker-compose run \ --name jupyter-lab-container \ --rm \ -e USERNAME=$(whoami) \ --service-ports \ jupyter-lab
起動ログにエラーがなく、次のように 127.0.0.1:8888
で Listen していれば上手くいっている。
$ ss -tlnp | grep 8888 LISTEN 0 128 127.0.0.1:8888 0.0.0.0:*
JupyterLab の Web UI にアクセスする
これでリモートサーバ上では JupyterLab が動いたけどループバックアドレスなので疎通がない。 そこで SSH Port Forwarding を使ってリモートサーバ上のポートをローカルに引き出してくる。
今回は Vagrant を使って環境を作っているので次のようにする。
$ vagrant ssh-config > ssh.config $ ssh -F ssh.config -L 8888:localhost:8888 default
ブラウザで localhost:8888
にアクセスする。
$ open http://localhost:8888
以下のような Web UI が見えればおっけー。 Jupyter Notebook よりも、ちょっと IDE っぽい見た目。
いじょう。
スマートPythonプログラミング: Pythonのより良い書き方を学ぶ
- 作者: もみじあめ
- 発売日: 2016/03/12
- メディア: Kindle版
- この商品を含むブログ (1件) を見る