Blow Up by Black Swan

Docker上でubuntuをベースにPythonのjupyter環境を構築する方法

今回は、docker上でubuntu18.04バージョンをベースにjupyter環境を構築してみました。以前、Dockerのまとめ記事を書いた時にCentOSベースでjupyter環境を構築しているので、わざわざ作る必要ないんじゃないかと言われそうですが、先日ふと気になってサーバOSの世界的なシェアを調べたところ、おそらくWindows Serverについでシェアが高いのが、ubuntuらしかったので、こういう機会に慣れてしまおうと思い立ったのが、今回の構築の理由です。

ちなみに日本では、ubuntuよりもCentOSの方がシェアが高いらしいです。サーバOSの記事については、Wikipediaが面白かったので、リンクを貼っておきます。

Wikipedia – Usage share of operating systems

今回の取り組みですが、同じLinux系のCentOSで既に構築しているという軽い気持ちで始めたにも関わらず、かなり苦戦し、4日間くらいひたすら格闘し続けました・・・。そんなこんなのubuntuベースのjupyter環境ですが、せっかくの苦労もあるので、備忘録がてら記事にしましたので、どなたかの参考になれば幸いです。

全体の構成としては、dockerコンテナ上で一から構築する方法とさらにそれを落とし込んだdockerfileの記述の2部構成です。コンテナでの構築とdockerfileでの記述は諸般の事情で少し異なる点がありますので、その点も改正しています。構築環境や利用したパッケージ等のバージョンは以下になります。

  • ホストOS: macOS High Sierra
  • docker ver: 18.06
  • ubuntu ver: 18.04
  • git ver: 2.19.1
  • pyenv ver:1.2.7

なお、gitについては最新バージョンを導入するために単純なapt install gitコマンドだけの実行とは異なっています。

1. 全体像

全体の流れは、以下になります。

  1. gitの導入
  2. pyenvの導入
  3. Pythonとjupyterの導入
  4. jupyter notebookの起動

基本的な流れは、gitを活用してpyenvを入れ、python3系とjupyterを導入するというものです。git cloneからのpyenvの流れは、Pythonを導入するときによく見る流れだなという印象があります。下記でより具体的な流れを説明しますが、そのコマンドを実行する前にdockerコンテナを生成してください。

$ docker run -it --name <任意の名前> -p 8888:8888 -v <任意のホストディレクトリ、ボリューム> ubuntu:latest

1-Ⅰ gitの導入

まずは、gitの導入からです。gitは最新バージョンを導入する方法です。

1. リポジトリ一覧の更新

~$ apt-get update

aptコマンドはapt-getapt-cacheを統合するためのコマンドとして作られたものです。一部の挙動は未だ違いますが、installなどの汎用的なコマンドは利用可能です。

念のためですが、私はリポジトリをいろんなパッケージが入った倉庫のようなイメージで捉えていて、パッケージはアプリケーションやひとまとまりのツールボックスのようなものとして捉えており、そんなイメージ感でいいのかなと思います。リポジトリは複数設定できるのですが、設定したものの漏れがないようにするために更新します。

2. リポジトリ追加用のコマンド(“apt-add-repository”)を入手

~$ apt install -y software-properties-common

インストールされるこのsoftware-properties-commonパッケージは、リポジトリの追加などのリポジトリを管理するためのコマンドを提供するパッケージです。これにより、apt-add-repositoryというリポジトリを追加するためのコマンドが手に入ります。ちなみに、オプションの-yは、ダウンロードの実行を確認するための質問などに自動でyesと答えるためのコマンドです。

3. 最新のgitを含むリポジトリを追加

~$ apt-add-repository -y ppa:git-core/ppa

PPAとは、ubuntu向けの非公式のリポジトリのことを言うようです。”git-core/ppa”はgitサイトで推奨されているリポジトリで、最新バージョンのgitを入手することができます。

4. リポジトリ一覧を更新

~$ apt update

新しいリポジトリを追加したので、リポジトリ一覧を更新します。

5. gitをインストール

~$ apt install -y git

6. 最新バージョンであることが確認

git --versionコマンドを実行することで、入手したgitのバージョンが確認できます。

7. vimを入手

~$ apt install -y vim

環境設定の設定などのためにvimをインストールしておきます。最新バージョンのvimは、通常のリポジトリからインストールできます。ちなみに、当初は最新版の入手にはソースからのインストールが必要だと思い込んでおり、色々とやってみましたが、見事ドツボにはまり、挫折しました・・・

1-Ⅱ pyenvの導入

次は、先ほど導入したgitを利用してpyenvをインストールしていきます。

1. "git clone"からpyenvを導入

~$ git clone https://github.com/pyenv/pyenv.git ~/.pyenv

~/.pyenvディレクトリにgitがインストールされます。

2. 環境変数の設定

pyenvインストール時についてくるコマンドを使えるように環境変数を設定します。ubuntu向けでは、~/.bash_profileではなく~/.bashrcに変数を書き込みます。

echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc
echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc
echo 'if command -v pyenv 1>/dev/null 2>&1; then\n eval "$(pyenv init -)"\nfi' >> ~/.bashrc

source ~/.bashrc

最後にsourceコマンドで~/.bashrcファイルを再読み込みしています。vimやcatコマンドで書き込み内容を確認できます。

3. 関連パッケージのインストール

[code lang="Bash"]
apt install -y make build-essential libssl-dev zlib1g-dev \
libbz2-dev libreadline-dev libsqlite3-dev \
wget curl llvm libncurses5-dev xz-utils tk-dev \
libxml2-dev libxmlsec1-dev libffi-dev

Pythonのインストールのために必要となる各種パッケージをインストールします。途中で地域とタイムゾーンについて質問されます(この点がdockerfileへの落とし込みの時に若干ネックになったところでした。下記に記載しています)。

1-Ⅲ Pythonとjupyterの導入

1-ⅡでPythonの導入環境が整ったため、Pythonの導入を進めていきます。

1. pythonをインストール

~$ pyenv install <任意のバージョン>

pyenv install --listでインストールできるPythonやanacondaのバージョンをチェックできます。

2. インストールしたpythonを標準使用のPythonに設定

~$ pyenv global <インストールしたバージョン>

3. pipのアップグレード

~$ pip install --upgrade pip

Pythonのパッケージ管理モジュールであり、標準で装備されているpipのバージョンをアップグレードします。

4. jupyterのインストール

~$ pip install jupyter

1-Ⅳ jupyterの設定と起動

最後にjupyterの設定を行います。

1. jupyterの設定

~/.jupyter/jupyter_notebook_config.pyファイルを作成し、そこに設定を書き込んでいきます。

~$ mkdir ~/.jupyter #ディレクトリの作成
~$ touch ~/.jupyter/jupyter_notebook_config.py #ファイルの作成

上記ファイルにvimなどを利用して以下を記入します。

c = get_config()
c.NotebookApp.ip = '*'
c.NotebookApp.open_browser = False
c.NotebookApp.port = 8888
c.NotebookApp.password = u'<パスワードのハッシュ値>'

パスワードのハッシュ値の簡易的な入手の仕方は以下になります。

ipython

[1] from notebook.auth import passwd

[2] passwd()
Enter password: <任意のパスワードを入力>
Verify password: <パスワードの確認>

[3] `sha1:<パスワードのハッシュ値>'

以上でjupyterの設定まで完了しました。最後に以下のコマンドを打つことでjupyterサーバが立ち上がり、ホストのブラウザからアクセスできるはずです。

~$ jupyter notebook --allow-root --port=8888 --ip=0.0.0.0 --no-browser

2. dockerfileにする場合の記述

次は、上記のdockerコンテナの作成をdockerfileに明示的に落とし込んだものです。
<dockerfileへの記述内容>

FROM ubuntu:latest

# "tzdata"をこの時点でインストールしている
RUN apt-get update && \
    apt-get install -y software-properties-common \
                       tzdata

RUN apt-add-repository -y ppa:git-core/ppa && \
    apt-get update && \
    apt-get install -y git \
                       vim

RUN git clone https://github.com/pyenv/pyenv.git ~/.pyenv
RUN echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc && \
    echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc

RUN echo 'if command -v pyenv 1>/dev/null 2>&1; then\n  eval "$(pyenv init -)"\nfi' >> ~/.bashrc

RUN apt-get install -y make build-essential libssl-dev zlib1g-dev \
                       libbz2-dev libreadline-dev libsqlite3-dev wget \
                       curl llvm libncurses5-dev xz-utils tk-dev \
                       libxml2-dev libxmlsec1-dev libffi-dev

ENV PATH $PATH:/root/.pyenv/bin

RUN pyenv install 3.6.5 && \
    pyenv global 3.6.5 && \
    pyenv rehash

ENV PATH $PATH:/root/.pyenv/shims

RUN pip install --upgrade pip && \
    pip install jupyter

RUN mkdir workbook \
          ~/.jupyter && \
    touch ~/.jupyter/jupyter_notebook_config.py

ビルド時に上から順に実行されていきますが、ここでのポイントは一番最初のインストール時点でtzdataパッケージをインストールしていることです。dockerコンテナ作成時点でPythonのインストールのために関連パッケージをインストールしましたが、その際にタイムゾーンに関する質問が出されました。dockerfileに、dockerコンテナ作成と同じような流れで記述してしまうと、この質問によってビルドが妨げられ、必ず失敗してしまいます。

これは、gitが何かしらと競合してしまっていることが原因らしいので、この競合を回避するために先にタイムゾーンに関連するパッケージtzdataをインストールしてしまいます。これによって、その後の関連パッケージ群のRUN時に出てくる質問が自動で解決され、dockerfileのビルドに成功することができます。

3. まとめ

今回は、docker上でubuntuをベースにPython、jupyter環境を構築する方法についてまとめました。用意されているイメージを使えば良いじゃないかと言われそうですが、用意されているイメージだとバージョンが古かったり、汎用性を持たせるために不要なパッケージまで入ってたり、自分なりのフォルダ構成をコンテナ作成後に作らないといけなかったりと行ったことがあるので、自分で作ってみました。

1番の目的は、dockerになれる、ubuntuに慣れる、ではあったんですけどね。今回、ubuntuをベースとすることで、LinuxのDebian系と言われるコマンドを学習することも非常に有意義だったと思います。どなたかの参考になれば幸いです。

4. 参考サイト

以下が今回の記事の参考サイトになります。一番参考にしたのはそれぞれの公式ドキュメントですが、検索すればすぐに出てくるので、割愛しています。