Vagrant x DockerでPredictionIOを試す

# はじめに
PredictionIOの勉強会に参加したので、とりあえず動かしてみようと思いました。
環境は何となく楽そうなDockerを選択。(楽じゃなかった。。)

# 前提：私の環境
Windows 10 Pro (64bit)
Git for Windows (Git Bash)

# VMの準備
## Hyper-Vの無効化
VirtualBoxを利用していきますが、Hyper-Vと共存できないので
こちらの記事を参考にbatファイルを作成して無効化しておきます。
[Hyper-VとVMware/VirtualBoxは共存不可！？](http://itengine.seesaa.net/article/440244402.html)

## VirtualBoxのインストール
まずはVirtualBoxをインストールします。
今回インストールしたのは VirtualBox 5.1.14 です。
[Download VirtualBox](https://www.virtualbox.org/wiki/Downloads)

## Vagrantのインストール
次にvagrantをインストールします。
今回インストールしたのは Vagrant 1.9.1 です。
[DOWNLOAD VAGRANT](https://www.vagrantup.com/downloads.html)

## ディレクトリの作成
VM用のディレクトリを用意します。
適宜好きな場所に。

```bash
$ cd /c/opt
$ mkdir -p vagrant/machines/predictionio
$ cd vagrant/machiens/predictionio
```

### Vagrantfileの生成
構成ファイルを生成します。
boxはubuntu/trusty64をベースとしてDockerを導入をするより
16.04 LTSでDockerも入っているboxが[Vagrantbox.es](http://www.vagrantbox.es/)に公開されているのでこちらを利用します。
vagrant box addに結構時間が掛かります。

```bash
$ vagrant box add ubuntu/docker https://github.com/jose-lpa/packer-ubuntu_lts/releases/download/v3.1/ubuntu-16.04.box
$ vagrant init --minimal ubuntu/docker
```

## ポートフォワーディングの設定
Vagrantfileに、あとでpredictionioで利用するポートをforwarded_portで追記しておきます。

```diff:Vagrantfile
Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu/docker"
+ config.vm.network "forwarded_port", guest: 8000, host: 8000, auto_correct: true
end
```

## メモリの設定
後述のDockerイメージのビルド時にメモリ不足にならないように
VagrantfileにVMのメモリ設定をします。

```diff:Vagrantfile
Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu/docker"
  config.vm.network "forwarded_port", guest: 8000, host: 8000, auto_correct: true
+ config.vm.provider "virtualbox" do |vb|
+  vb.memory = "2048"
+ end
end
```

## 起動してログイン
VMを起動、ログインします。

```bash
$ vagrant up
$ vagrant ssh
```

## DNSの設定
Dockerイメージのビルドの為にDNSを設定しておきます。
(参考：[Ubuntuでのresolv.confの扱い](http://qiita.com/uchiko/items/eb0665f528e2bb792f47))

```bash
$ sudo vim /etc/network/interfaces
```

```diff:/etc/network/interfaces
# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).

source /etc/network/interfaces.d/*

# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
auto eth0
iface eth0 inet dhcp
pre-up sleep 2

+dns-nameservers 8.8.8.8
```

設定反映

```bash
$ sudo service networking restart
```

# Dockerの準備

## Dockerファイルの取得
[Docker Installation for PredictionIO](http://predictionio.incubator.apache.org/community/projects/#docker-installation-for-predictionio)にある通り、v0.10.0を利用している[steveny2k/docker-predictionio](https://github.com/steveny2k/docker-predictionio)のリポジトリをcloneしてきます。
＊なお、Docker Hubにも色々とイメージが転がっていますが、PredictionIOのバージョンが古いと後で詰まるので要注意([このイメージ](https://hub.docker.com/r/steveny/predictionio/)ならいけるかも？)

```bash
$ git clone https://github.com/steveny2k/docker-predictionio.git
$ cd docker-predictionio
```

## Dockerイメージのビルドと起動
[REDME](https://github.com/steveny2k/docker-predictionio/blob/master/README.md)に従ってビルド・起動してみます。
Dockerイメージのビルドはかなり時間が掛かります。

```bash
$ docker build -t predictionio .
$ docker run -p 8000:8000 --name predictionio_instance -it predictionio /bin/bash
```

# PredictionIOを動かす

## 関連ライブラリのインストール
Dockerのコンテナ環境にログインしたら、以下の関連ライブラリをインストールします。
また、設定ファイルの編集用にvimもインストールしておきます。

```bash
# apt-get update
# apt-get install sudo
# apt-get install vim

# pip install --upgrade pip
# pip install setuptools
# pip install predictionio
```

## PredictionIOサーバの起動
起動に成功すると「Your system is all ready to go.」と表示されます。

```bash
# pio-start-all
# pio status
```

## Engineの取得・起動
### Engineを取得

```bash
# mkdir ~/MySimilarProduct
# pio template get apache/incubator-predictionio-template-similar-product ~/MySimilarProduct
# cd ~/MySimilarProduct/
```

### AppNameを登録してAccessKeyを取得

```bash
# pio app new MyApp1
```

### AppNameをengine.jsonに設定

```diff:engine.json
---  
  "datasource": {
    "params" : {
-     "appName": "INVALID_APP_NAME"
+     "appName": "MyApp1"
    }
---
```

### 学習データの投入

```bash
# python data/import_eventserver.py --access_key [取得したキー]
```

### Engine Templateのビルドとトレーニング

```bash
# pio build --verbose
# pio train
```

trainがStackoverflowでこける場合には、とりあえずengine.jsonの修正で逃げる

```diff:engine.json
---  
  "algorithms": [
    {
      "name": "als",
      "params": {
        "rank": 10,
-       "numIterations": 20,
+       "numIterations": 10,
        "lambda": 0.01,
        "seed": 3
      }
    }
  ]
---
```


## 起動確認
以下にアクセスして起動を確認します。
[http://localhost:8000](http://localhost:8000)

## Todo
とりあえずここまで。
あとは、実際に色々なEngineを試してみたい。

# 参考
- [VagrantとDockerについて名前しか知らなかったので試した](http://qiita.com/hidekuro/items/fc12344d36d996198e96)
- [RE:PredictionIOから始めるレコメンド生活 ― 1. 環境構築・動作確認編 ―](http://qiita.com/terukizm/items/dc0a53944c11653ef406#1-%E7%92%B0%E5%A2%83%E6%A7%8B%E7%AF%89%E5%8B%95%E4%BD%9C%E7%A2%BA%E8%AA%8D)
- [Hyper-VとVMware/VirtualBoxは共存不可！？](http://itengine.seesaa.net/article/440244402.html)
- [Ubuntuでのresolv.confの扱い](http://qiita.com/uchiko/items/eb0665f528e2bb792f47)