Azure 仮想マシンの Ubuntu に Apache2 + Django + OpenCV + keras のWebアプリを配置する

## はじめに

Ubuntu 18.04.2 LTS に Apache2 を導入して Django + OpenCV + keras の顔分類Webアプリを配置してみます。

前回：[Ansibleを利用してAzure仮想マシンを作成する](https://qiita.com/kerobot/items/c2718a53ef61b70f6046)
前々回：[Ansibleを利用してAzure仮想マシンを作成するためのAzure資格情報の作成と準備](https://qiita.com/kerobot/items/42d234df680772bedf0d)

配置するWebアプリは以前作成したものです。

[【顔分類その６】Djangoとkerasを利用した本田翼か佐倉綾音かを分類するWebアプリ](https://qiita.com/kerobot/items/65d4e1942a31c00317e2)

Webアプリの配置も Ansible で自動化してみようとしましたが挫折しました…。

## WSL (Ubuntu 18.04.2 LTS) から Azure 仮想マシンの Ubuntu に接続して初期設定

* 作成した Azure 仮想マシンの Ubuntu に対して、ユーザーとIPアドレスを指定して SSH で接続します。

```bash
#!/bin/bash
ssh azureuser@xxx.xxx.xxx.xxx
```

* 異なる環境から Azure 仮想マシンの Ubuntu に接続する場合は、authorized_keys に公開鍵を追加します。

```bash
#!/bin/bash
azureuser@ubuntu01:~$ vi ~/.ssh/authorized_keys
```

* バージョンを確認してみます。

```bash
#!/bin/bash
azureuser@ubuntu01:~$ cat /etc/os-release
```

* aptコマンドのリポジトリを ubuntu.com から jp に切り替えます。

```bash
#!/bin/bash
azureuser@ubuntu01:~$ sudo sed -i -e 's%http://.*.ubuntu.com%http://ftp.jaist.ac.jp/pub/Linux%g' /etc/apt/sources.list
```

* aptコマンドでパッケージをアップデートします。

```bash
#!/bin/bash
azureuser@ubuntu01:~$ sudo apt update
azureuser@ubuntu01:~$ sudo apt upgrade
```

* 日本語化してみます。

```bash
#!/bin/bash
azureuser@ubuntu01:~$ # 日本語言語パックのインストール
azureuser@ubuntu01:~$ sudo apt -y install language-pack-ja
azureuser@ubuntu01:~$ # ロケールを日本語に設定
azureuser@ubuntu01:~$ sudo update-locale LANG=ja_JP.UTF8
azureuser@ubuntu01:~$ # Ubuntuを再起動
azureuser@ubuntu01:~$ sudo shutdown -r now
azureuser@ubuntu01:~$ # タイムゾーンをJSTに設定
azureuser@ubuntu01:~$ sudo dpkg-reconfigure tzdata
azureuser@ubuntu01:~$ # 日本語マニュアルのインストール
azureuser@ubuntu01:~$ sudo apt -y install manpages-ja manpages-ja-dev
azureuser@ubuntu01:~$ # 現在のロケール設定を確認
azureuser@ubuntu01:~$ locale
azureuser@ubuntu01:~$ # カレンダーを表示してみる
azureuser@ubuntu01:~$ cal
azureuser@ubuntu01:~$ # 日時を表示してみる
azureuser@ubuntu01:~$ date
```

## Apache2 の導入

* Apache2 と mod-wsgi-py3 をインストールします。

```bash
#!/bin/bash
azureuser@ubuntu01:~$ sudo apt update
azureuser@ubuntu01:~$ sudo apt install -y apache2
azureuser@ubuntu01:~$ sudo apt install -y apache2-dev
azureuser@ubuntu01:~$ sudo apt install -y libapache2-mod-wsgi-py3
```

## Python3（関連）の導入

* Python3 の pip と venv と OpenCV で利用する lib たちをインストールします。

```bash
#!/bin/bash
azureuser@ubuntu01:~$ sudo apt update
azureuser@ubuntu01:~$ sudo apt install -y python3-pip
azureuser@ubuntu01:~$ sudo apt install -y python3-venv
azureuser@ubuntu01:~$ sudo apt install -y libsm6
azureuser@ubuntu01:~$ sudo apt install -y libxext6
azureuser@ubuntu01:~$ sudo apt install -y libxrender-dev
```

## GitHub から Webアプリをクローン

* GitHubから顔分類Webアプリをクローンしてきます。

```bash
#!/bin/bash
azureuser@ubuntu01:~$ cd ~
azureuser@ubuntu01:~$ git clone https://github.com/kerobot/img_pred_web.git img_pred_web
```

## Python3 の仮想環境を作成して Python パッケージをインストール

* 顔分類Webアプリのための Python3 の仮想環境を作成して有効化します。

```bash
#!/bin/bash
azureuser@ubuntu01:~$ cd ~/img_pred_web
azureuser@ubuntu01:~$ python3 -m venv venv
azureuser@ubuntu01:~$ source venv/bin/activate
```

* pipをアップデートして、必要な Python パッケージをインストールします。

```bash
#!/bin/bash
(venv) azureuser@ubuntu01:~$ python -m pip install --upgrade pip
(venv) azureuser@ubuntu01:~$ pip install -r requirements.txt
(venv) azureuser@ubuntu01:~$ pip install mod_wsgi
```

> pytz, Django, typed-ast, lazy-object-proxy, six, wrapt, astroid, isort, mccabe, pylint, numpy, opencv-python, Pillow, h5py, keras-applications, protobuf, gast, grpcio, termcolor, wheel, markdown, werkzeug, tensorboard, absl-py, astor, keras-preprocessing, tensorflow, pyyaml, scipy, keras + mod_wsgi がインストールされます。

* django-admin のバージョンを確認してみます。

```bash
#!/bin/bash
(venv) azureuser@ubuntu01:~$ django-admin --version
2.0.13
```

## Webアプリの設定

* settings.py の DEBUG と ALLOWED_HOSTS を編集します。

```bash
#!/bin/bash
(venv) azureuser@ubuntu01:~$ vi mysite/settings.py
```

```python
DEBUG = False
ALLOWED_HOSTS = ['127.0.0.1', 'xxx.xxx.xxx.xxx(パブリックIP)']
```

> ALLOWED_HOSTS には接続を許可するIPなどを設定します。

## django 関連の設定

* Django 管理コマンド manage.py を利用して諸々行います。

```bash
#!/bin/bash
(venv) azureuser@ubuntu01:~$ # データベースのマイグレート
(venv) azureuser@ubuntu01:~$ python manage.py migrate
(venv) azureuser@ubuntu01:~$ # 静的ファイルの収集
(venv) azureuser@ubuntu01:~$ python manage.py collectstatic
(venv) azureuser@ubuntu01:~$ # 管理ユーザーの作成
(venv) azureuser@ubuntu01:~$ python manage.py createsuperuser
```

## 権限関連の設定

* ディレクトリやデータベースファイルの権限を設定します。

```bash
#!/bin/bash
(venv) azureuser@ubuntu01:~$ chmod 755 ~/img_pred_web
(venv) azureuser@ubuntu01:~$ chmod 755 ~/img_pred_web/db.sqlite3
(venv) azureuser@ubuntu01:~$ sudo chown :www-data ~/img_pred_web
(venv) azureuser@ubuntu01:~$ sudo chown :www-data ~/img_pred_web/db.sqlite3
```

## mod_wsgi 関連の設定

* mod_wsgi のパスを確認します。

```bash
#!/bin/bash
(venv) azureuser@ubuntu01:~$ mod_wsgi-express module-config
LoadModule wsgi_module "/home/azureuser/img_pred_web/venv/lib/python3.6/site-packages/mod_wsgi/server/mod_wsgi-py36.cpython-36m-x86_64-linux-gnu.so"
WSGIPythonHome "/home/azureuser/img_pred_web/venv"
```

* 設定ファイルを作成します。

```bash
#!/bin/bash
(venv) azureuser@ubuntu01:~$ sudo vi /etc/apache2/sites-available/django.conf
```

```bash
# 先ほど確認した mod_wsgi のパス
LoadModule wsgi_module /home/azureuser/img_pred_web/venv/lib/python3.6/site-packages/mod_wsgi/server/mod_wsgi-py36.cpython-36m-x86_64-linux-gnu.so

# これを指定しないとハングする・・・WSGIアプリを最初のインタプリタ内で実行するため
WSGIApplicationGroup %{GLOBAL}
# mod_wsgi が利用する Python のパス
WSGIPythonHome /home/azureuser/img_pred_web/venv
# Apache2 へのリクエストをつなぐ先
WSGIScriptAlias / /home/azureuser/img_pred_web/mysite/wsgi.py
# 実行時に Python が参照するパス（WebアプリとPythonパッケージの場所を指定）
WSGIPythonPath /home/azureuser/img_pred_web:/home/azureuser/img_pred_web/venv/lib/python3.6/site-packages

# Apache2 のアクセスを許可するWebアプリのディレクトリ
<Directory /home/azureuser/img_pred_web/mysite>
  <Files wsgi.py>
    Require all granted
  </Files>
</Directory>

# django が利用する静的ファイルのパス
Alias /static/ /home/azureuser/img_pred_web/static/
# Apache2 のアクセスを許可するWebアプリの静的ファイルのディレクトリ
<Directory /home/azureuser/img_pred_web/static>
  Require all granted
</Directory>
```

* 既存のサイト設定 000-default を無効にします。

```bash
#!/bin/bash
(venv) azureuser@ubuntu01:~$ sudo a2dissite 000-default
```

* 作成したサイト設定 django を有効にします。

```bash
#!/bin/bash
(venv) azureuser@ubuntu01:~$ sudo a2ensite django
```

## Apache2 のサービス設定

* Apache2 のサービスをリロードします。

```bash
#!/bin/bash
(venv) azureuser@ubuntu01:~$ sudo systemctl reload apache2
```

* Apache2 のサービス自動起動を有効化します。

```bash
#!/bin/bash
(venv) azureuser@ubuntu01:~$ sudo systemctl enable apache2
```

## ブラウザからアクセスしてみる！

* ブラウザを起動してサーバーに接続してみます。

* 繋がりました。やった！
![本田翼か佐倉綾音](https://qiita-image-store.s3.amazonaws.com/0/283306/2ec756c3-7606-767d-3835-d0f5d5921fdc.jpeg)

## おわりに

Django のWebアプリを manage.py runserver ではなく Apache2 で動作させてみました。
Apache2 へのリクエストを WSGI を介して Python に繋げる流れがなんとなく理解できたと思います。

keras を呼び出すためには、Python のサブインタープリタ内ではなく、最初のインタプリタ内で実行しないといけないということがわからず結構はまりました。
結果として、WSGIApplicationGroup %{GLOBAL} を指定して動作しましたが、このあたりの理解が甘々なので、もっと調べてみようと思います。