Bluemix NLTK,MeCab,Watson API のコンテナのビルド 忘備録

IBM Watson API や Pythonベースの日本語の自然言語処理に必要なツールが入った IBMコンテナ（Dockerコンテナ）をビルドして、IBM Bluemix のリポジトリに登録して、再利用できる様にします。 開発環境用のコンテナですから、もちろんコンテナが継続して実行する工夫もします。

# Dockerコンテナのビルド環境の構築

目的のDockerコンテナは、自己のPC環境でビルドして、Bluemix のコンテナのリポジトリーに登録していきます。ビルドする環境は Ubuntu Linux の Docker が便利ですから、最初に自己のPC環境に Vagrantで Ubuntu Linux が動作する環境を作ります。
ここでは Vagrant の環境を準備する方法は以下のリンクが参考になると思います。

* [Vagrant by HashiCorp](https://www.vagrantup.com/)
* [Qiita Windows + Vagrant + Ubuntu 14.04](http://qiita.com/shinichi62/items/1050f89ed693e3baa3f8)

Vagrant環境ができたら、Ubuntu Linux の仮装マシンを起動して、Docker.ioをインストールします。

次に、クラウド・ファウンドリーの cf コマンド と Bluemix の bx コマンドをインストールして、Bluemix のアカウントにログインします。 もちろん Bluemix のアカウント取得は必須です。これらの前提条件を整えるには、以下のリンクが参考になります。

* [Bluemix のフリー・アカウント作成] (https://console.ng.bluemix.net/)
* [Bluemix CLI コマンドのインストール](https://console.ng.bluemix.net/docs/cli/index.html#downloads)
* [Bluemix cf ic プラグインのインストール](https://console.ng.bluemix.net/docs/containers/container_cli_cfic_install.html)



# Dockerfile の雛形の取得と編集

日本語処理のツールとしては、Pythonで作られたNLTKが便利なので、最新のPythonが実行できるコンテナを作っていきます。 Pythonの最新環境のDockerfileの雛形として、Dockerのオフィシャル・イメージを利用するので、以下のコマンドで、Vagrant の Ubuntu上で Dockerfile をクローンします。 この雛形には、Python 2.7系、3系のすべての雛形がありますが、今回は Python 2.7 を利用してます。

~~~console
root@ubuntu-xenial:~/docker# git clone https://github.com/docker-library/python
~~~

Python 2.7 のディレクトリに移動して Dockerfile を編集します。 

~~~console
root@ubuntu-xenial:~/docker/python# ls
2.7  3.6                          Dockerfile-slim.template               README.md
3.3  Dockerfile-alpine.template   Dockerfile-windowsservercore.template  update.sh
3.4  Dockerfile-debian.template   generate-stackbrew-library.sh
3.5  Dockerfile-onbuild.template  LICENSE
root@ubuntu-xenial:~/docker/python# cd 2.7
root@ubuntu-xenial:~/docker/python/2.7# ls
alpine  Dockerfile  onbuild  slim  wheezy  windows
~~~

編集する箇所を以下にリストしますから、オリジナルのDockerfileに追加します。

~~~text:Dockerfile
     1	FROM buildpack-deps:jessie
     2	ADD ./app /app
     3	
<中略>
    10	
    11	# runtime dependencies
    12	RUN apt-get update && apt-get -y upgrade && apt-get install -y --no-install-recommends \
    13			tcl \
    14			tk \
    15			mecab \
    16			libmecab-dev \
    17			mecab-ipadic \
    18			mecab-ipadic-utf8 \
    19			mecab-utils \
    20			emacs-nox \
    21			nmon \
    22		&& rm -rf /var/lib/apt/lists/*
~~~

追加の箇所の説明を以下に列挙します。

* 2行目 コンテナの終了を止めるシェルの入ったディレクトリで、この後に解説します。
* 12行目 apg-get -y upgrade を追加します。Ubuntu 14.04 では OpenSSLに重大な脆弱性があり、対策としてアップグレードします。
* 15行目〜19行目 形態素解析のための MeCab と辞書を追加します。
* 20行目は ファイル編集のためのツールの追加です。 お好みで置き換えてください。
* 21行目は OSの動作状況を表示するモニタリングツールの追加です。Dockerコンテナのホストマシンの動作状態を知ることができますから、反応が遅い時にホストマシンのCPU状態を知る事ができるので便利です。

~~~text:Dockerfile
    77	RUN pip install --no-cache-dir mecab-python
    78	RUN pip install --no-cache-dir watson-developer-cloud
    79	RUN pip install --no-cache-dir BeautifulSoup
    80	RUN pip install --no-cache-dir nltk
~~~
続きの修正箇所を列挙します。

* 77行目 MeCab の Python APIライブラリの追加です。
* 78行目 WatsonAPI の Python ライブラリの追加です。
* 79行目 ウェブスクレイビングのツールの追加です。
* 80行目 自然言語ツールキットの追加です。

~~~text:Dockerfile
    80	RUN pip install --no-cache-dir nltk
    81	
    82	CMD ["bash", "/app/loop_wait"]
~~~
最後に コンテナが終了しない様に、無限ループでsleepを実行するコマンドを実行します。


## コンテナ継続実行のための工夫
前述の ADD ./app /app の解説です。 2.7のフォルダーに、appのディレクトリを作成して、以下のファイル作成して、実行権 chmod +x loop_waitを与えます。

~~~bash:loop_wait
#!/bin/bash
while true; do sleep 60; done
~~~

このファイルを Dockerfileの最終行 82行目の CMDから実行することで、コンテナを継続実行させます。


# コンテナのビルドとBluemixリボジトリへの登録
自己のvagrantの環境で、コンテナをビルドします。 Dockerfile ファイルと app ディレクトリのある場所で、以下のコマンドを実行します。 必要なパッケージをコンテナにインストールして、ファイルを集めPython 2.7.13 をコンパイルして、コンテナをビルドします。このコンテナをビルドするのに10分くらい必要かもしれません。

~~~console
root@ubuntu-xenial:~/python/2.7# docker build -t mynode:python .
~~~


ビルドが完了すると、以下の様なメッセージ出ますから、ビルドの成功を知る事ができます。

~~~
Step 9 : RUN pip install --no-cache-dir virtualenv
 ---> Running in 3259e634ff72
Collecting virtualenv
  Downloading virtualenv-15.1.0-py2.py3-none-any.whl (1.8MB)
Installing collected packages: virtualenv
Successfully installed virtualenv-15.1.0
 ---> b95cc31c623c
Removing intermediate container 3259e634ff72
Step 10 : CMD python2
 ---> Running in 3fb0181e560c
 ---> 25903811171b
Removing intermediate container 3fb0181e560c
Successfully built 25903811171b
~~~

次に Bluemix のリポジトリの名前を取得します。 cf コマンドは、BluemixのベースとなっているクラウドファンドリーのCLIツールで、その後のicは、Dockerのプラグインを指すサブコマンドです。

~~~console
root@ubuntu-xenial:~/docker/python/2.7# cf ic namespace get
takara_node
~~~

ローカルのコンテナに、Bluemix のリポジトリのタグを付けます。

~~~console
root@ubuntu-xenial:~/docker/python/2.7# docker tag mynode:python registry.ng.bluemix.net/takara_node/python
~~~

次のコマンドで、Bluemix のリポジトリへ、ビルドしたコンテナを登録します。

~~~console
root@ubuntu-xenial:~/docker/python/2.7# docker push registry.ng.bluemix.net/takara_node/python
~~~

次のコマンドでBluemixの登録された共通コンテナと自分の登録したコンテナをリスクする事ができます。最終行に、pythonコンテナが登録されている事が解ります。

~~~console
root@ubuntu-xenial:~/docker/python/2.7# cf ic images
REPOSITORY                                    TAG                 IMAGE ID            CREATED             SIZE
registry.ng.bluemix.net/ibmnode               latest              acec21732cb5        11 days ago         192.5 MB
registry.ng.bluemix.net/ibmnode               v4                  acec21732cb5        11 days ago         192.5 MB
<中略>
registry.ng.bluemix.net/ibmliberty            webProfile7         6b2b8341fa32        5 weeks ago         276 MB
registry.ng.bluemix.net/takara_node/mynode1   latest              721caef84790        12 days ago         190.9 MB
registry.ng.bluemix.net/takara_node/python    latest              17f60ad04c10        2 hours ago         334.4 MB
~~~

この状態で、Bluemix ポータルでカタログを見ると、上記のコンテナが表示されているはずです。 右下に、紫色で python というコンテナが表示されています。
![スクリーンショット 2017-02-18 10.42.43.png](https://qiita-image-store.s3.amazonaws.com/0/42829/2927e796-bf4b-96c0-202d-6c0480138a4e.png)


# コンテナの起動とログイン

ウェブのポータル画面からも実行できますが、次のCLIコマンドでもコンテナを開始できます。

~~~console
root@ubuntu-xenial:~/python/2.7# cf ic run --name python -m 512 registry.ng.bluemix.net/takara_node/python:latest
~~~

初回はコンテナのビルドに約１分くらいかかります。ビルド中は以下のcf ic ps コマンドでビルド中であることを知る事ができます。

~~~console
root@ubuntu-xenial:~/python/2.7# cf ic ps
CONTAINER ID        IMAGE                                                COMMAND             CREATED             STATUS                    PORTS                          NAMES
edd1f16c-625        registry.ng.bluemix.net/takara_node/python:latest    ""                  15 seconds ago      Building 14 seconds ago                                  python
~~~

この様子は、Bluemixポータルからも確認ができます。
コンテナのビルド中状態
![スクリーンショット 2017-02-18 11.08.15.png](https://qiita-image-store.s3.amazonaws.com/0/42829/b1fdbdbd-fb4f-d2ab-700b-484a1b81cc6a.png)

ビルド完了状態
![スクリーンショット 2017-02-18 11.11.17.png](https://qiita-image-store.s3.amazonaws.com/0/42829/60a93477-e024-dd01-7b76-7fde9f6692a7.png)

コンテナの詳細画面
![スクリーンショット 2017-02-18 11.17.51.png](https://qiita-image-store.s3.amazonaws.com/0/42829/77d2f0cd-6e44-8eb6-51d3-619e4672624b.png)

## コンテナへのログイン
次のコマンドで、コンテナへログインして、シェルからコマンドを実行できる様になります。

~~~console
root@ubuntu-xenial:~/docker/python/2.7# cf ic exec -it python /bin/bash
root@instance-003624a8:/# ps -ax                                                                                                                                
    PID TTY      STAT   TIME COMMAND
      1 ?        Ss     0:00 bash /app/loop_wait
     18 ?        Ss     0:00 /bin/bash
     24 ?        S      0:00 sleep 60
     25 ?        Ss     0:00 /bin/bash
     31 ?        R+     0:00 ps -ax
~~~

# その他 Docker コマンド

コンテナの停止には、stop を利用します。

~~~console
root@ubuntu-xenial:~/python/2.7# cf ic ps
CONTAINER ID        IMAGE                                                COMMAND             CREATED             STATUS                PORTS                          NAMES
cea800cf-862        registry.ng.bluemix.net/takara_node/python:latest    ""                  6 hours ago         Running 6 hours ago                                  python
26dba932-cc4        registry.ng.bluemix.net/takara_node/mynode1:latest   ""                  12 days ago         Running 12 days ago   169.46.19.213:3000->3000/tcp   mynode1
root@ubuntu-xenial:~/python/2.7# cf ic stop cea800cf-862
cea800cf-862
~~~

コンテナの削除するには、rm を利用します。

~~~console
root@ubuntu-xenial:~/python/2.7# cf ic rm cea800cf-862
cea800cf-862
~~~

コンテナのイメージの削除には、rmi を利用します。

~~~console
root@ubuntu-xenial:~/python/2.7# cf ic images
REPOSITORY                                    TAG                 IMAGE ID            CREATED             SIZE
<中略>
registry.ng.bluemix.net/takara_node/python    latest              8cd32e284563        7 hours ago         310.2 MB

root@ubuntu-xenial:~/python/2.7# cf ic rmi registry.ng.bluemix.net/takara_node/python 
Untagged: sha256:8cd32e2845639a3fad5bd6e26c7a57c3f69539cebbd846535bb99b634aa8b324
~~~

ローカル環境でビルドに利用したイメージを削除するには、dockerコマンドを利用します。

~~~console
root@ubuntu-xenial:~# docker images
REPOSITORY                                    TAG                 IMAGE ID            CREATED             SIZE
mynode                                        python              8cd32e284563        7 hours ago         852 MB
registry.ng.bluemix.net/takara_node/python    latest              8cd32e284563        7 hours ago         852 MB

root@ubuntu-xenial:~# docker rmi mynode:python
Untagged: mynode:python

root@ubuntu-xenial:~# docker rmi registry.ng.bluemix.net/takara_node/python:latest
~~~

# 構築テスト

MeCabがインストールされている事の確認

~~~console
root@instance-003624a8:/# mecab -v
mecab of 0.996
~~~


PythonのNLTKの導入確認

~~~console
root@instance-003624a8:/# python
Python 2.7.13 (default, Feb 17 2017, 23:23:18) 
[GCC 4.9.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import nltk
>>> nltk.download()
NLTK Downloader
---------------------------------------------------------------------------
    d) Download   l) List    u) Update   c) Config   h) Help   q) Quit
---------------------------------------------------------------------------
Downloader> 
~~~