はじめに
- Azure App Service での OpenCV の環境構築は、比較的簡単でした。公式のドキュメントも丁寧だし、Azure CLI ツールの
--help
が充実している様に感じました。 - App Service は、Azureが用意している
組み込みイメージ
とDockerfile
を作成するカスタムイメージ
を利用できます。OpenCV は、後者のカスタムイメージを作成する必要があります。 - 今回も、以前作成した顔認識アプリを利用します。ソースコードは、同一です。Dockerfileが必要になる程度です。
- ソース一式は ここ です。
- 参考
概要
- Mac
- 顔認識アプリ
- Flask
- OpenCV
- Python
- デプロイツール等
- Azure CLI
- Docker
- Homebrew
- 顔認識アプリ
- Azure
- App Service on Linux
- Container Registry
顔認識アプリ
- 以下で解説したものと同一です。
- 以下のファイルは、同一です。解説は省略します。
- haarcascade_eye.xml
- haarcascade_frontalface_default.xml
- main.py
- requirements.txt
- templates/index.html
Dockerfile
- 元イメージは、
ubuntu:18.04
にしました。今回は、Python ですが、Node.js や PHP 等にも流用しやすいと考えたためです。 -
DEBIAN_FRONTEND=noninteractive
で、apt-get を非対話形式に出来ますね。 -
PYTHONUNBUFFERED=0
は、App Service で、ログを閲覧する時に有用なものです。例えば、print('Hello, Azure!')
など、標準出力が閲覧出来ます。設定しないと、標準エラーしか閲覧出来ない様です。 -
apt-get
でpython3
に最低限必要なパッケージをインストールします。 - 次に、OpenCVに必要な
libopencv-dev
をインストールします。また、pip でopencv-python
をインストールします。pip でインストールする理由は、pip パッケージの場合、マルチコアで動作してくれる、最新のバージョンである、などが理由です。 - そして、Azure のコンパネから ssh 接続するための
openssh-server
をインストールします。 - コンパネからの接続は、ユーザー名
root
パスワードDocker!
ポート2222
Ciphersaes128-cbc,3des-cbc,aes256-cbc
MACshmac-sha1,hmac-sha1-96
を設定する必要があります。 - 最後に、
CMD
で sshサーバーとgunicorn
経由でmain.py
のapp
を起動します。
FROM ubuntu:18.04
ENV DEBIAN_FRONTEND=noninteractive \
PYTHONUNBUFFERED=0
RUN apt-get update && apt-get install -y --no-install-recommends \
libopencv-dev \
openssh-server \
python3 \
python3-pip \
python3-setuptools \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
RUN echo "root:Docker!" | chpasswd && \
mkdir /var/run/sshd && \
sed -i 's/#Port 22/Port 2222/' /etc/ssh/sshd_config && \
sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config && \
sed -i '$ a Ciphers aes128-cbc,3des-cbc,aes256-cbc' /etc/ssh/sshd_config && \
sed -i '$ a MACs hmac-sha1,hmac-sha1-96' /etc/ssh/sshd_config
RUN mkdir /code
WORKDIR /code
ADD . /code/
RUN pip3 install -r requirements.txt
EXPOSE 2222 8000
CMD ["/bin/sh", "-c", "/usr/sbin/sshd && gunicorn --bind=0.0.0.0 --timeout 600 main:app"]
デプロイ
- Azure でアカウントを作成してください。
Azure CLI
- Mac用の手順です。その他の環境は、公式ページを参照してください。
$ brew install azure-cli
ログイン
- @outlook.com など Microsoftのアカウントでログイン出来ます。
$ az login
リソースグループの作成
- App Service、Container Registry 等のリソースを共通のグループとして管理するためのものです。
- リソースグループ名は
flask-opencv
にしました。ロケーションは、東日本(japaneast)にしました。
$ az group create --name flask-opencv --location japaneast
Container Registry の作成、ユーザー名、パスワード
- リソース名は
flaskopencv
にしました。Container Registry は-
が使えないのでした。 - リソースグループ名は、上記で作成した
flask-opencv
ですね。 - --sku は
Basic
です。無料のF1
は無いようです。残念。。。 - --admin-enabled は、既定で無効になっている管理者ユーザーを有効にしています。
- 最後に
username
とpassword
を確認します。今回はqBXsw4NcyMGmYe+AxbN9XTXtl8DmpzDI
ですね。
$ az acr create --name flaskopencv --resource-group flask-opencv --sku Basic --admin-enabled true
$ az acr credential show --name flaskopencv
{
"passwords": [
{
"name": "password",
"value": "qBXsw4NcyMGmYe+AxbN9XTXtl8DmpzDI"
},
{
"name": "password2",
"value": "qTSksf3ssm=330OxC0+VAaM1nYwOGzOv"
}
],
"username": "flaskopencv"
}
docker login、build、tag、push
- Container Registry へログインします。上記で取得したユーザーとパスワードを使います。
- Dockerfile を元に、build、tag を付与して、レジストリへ push します。
$ docker login flaskopencv.azurecr.io --username flaskopencv
$ docker build -t flask-opencv .
$ docker tag flask-opencv flaskopencv.azurecr.io/flask-opencv:latest
$ docker push flaskopencv.azurecr.io/flask-opencv:latest
App Service プランの作成
- App Service を Linux で作成します。リソース名やリソースグループ名は、上記と命名を一緒にしています。
- --sku は 無料の F1 が利用できます。
$ az appservice plan create --name flask-opencv --resource-group flask-opencv --sku F1 --is-linux
App Service の作成
- 上記で作成したプランに HTTPサービスである
webapp
を作成します。 - 上記で
docker push
したコンテナイメージを利用します。 - リソース名、リソースグループ名、リソースプラン名などは、共通としてます。
$ az webapp create --name flask-opencv --resource-group flask-opencv --plan flask-opencv --deployment-container-image-name flaskopencv.azurecr.io/flask-opencv:latest
App Service から Container Registry へのアクセスするための設定
- レジストリの名前、アドレス、ユーザー名、パスワードなどを設定しています。
$ az webapp config container set --name flask-opencv --resource-group flask-opencv --docker-custom-image-name flaskopencv.azurecr.io/flask-opencv:latest --docker-registry-server-url https://flaskopencv.azurecr.io --docker-registry-server-user flaskopencv --docker-registry-server-password qBXsw4NcyMGmYe+AxbN9XTXtl8DmpzDI
ポート設定
- Dockerfile で gunicorn を ポート 8000 で動かしている事を設定しています。
$ az webapp config appsettings set --name flask-opencv --resource-group flask-opencv --settings WEBSITES_PORT=8000
ログ設定
- コンテナ内で発生した、標準出力と標準エラーのログを閲覧出来る様にします。
- Dockerfile で
PYTHONUNBUFFERED=0
を設定しました。この環境変数が無いと、print('Hello Azure!')
など標準出力されないので注意して下さい。これで、4日程度悩みまくりました。たった1行の違いでした。。。
$ az webapp log config --name flask-opencv --resource-group flask-opencv --docker-container-logging filesystem
動作確認
- URL は App Service に指定したサービス名が含まれる https://flask-opencv.azurewebsites.net/ となります。
- 画像(jpeg)と処理回数(1〜100)を送信し、顔認識の画像を受信します。
- 処理回数は、性能評価用に準備したものです。今回は、10回にします。
送信画像と結果画像
- 顔認識に使う画像は、一部界隈ではおなじみの顔画像を使いました。
- Heroku用アプリ、Google App Engine用アプリ、Lambda用アプリで利用した物と同じです。
ログの確認
- 今回は、約16秒でした。1回あたり、1.6秒ですね。まぁまぁかな?
$ az webapp log tail --name flask-opencv --resource-group flask-opencv
2019-12-06T14:53:31.507178845Z opencv version: 4.1.2, elapsed second: 16.534130334854126
ssh接続
- Azure コンパネの開発ツールに ssh があります。
cpu確認
- Intel(R) Xeon(R) CPU E5-2660 0 @ 2.20GHz が 1個でした。
-
flags
にavx
があるから、TensorFlow
も動きそうだ。よし。
# cat /proc/cpuinfo
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 45
model name : Intel(R) Xeon(R) CPU E5-2660 0 @ 2.20GHz
stepping : 7
microcode : 0xffffffff
cpu MHz : 2199.978
cache size : 20480 KB
physical id : 0
siblings : 1
core id : 0
cpu cores : 1
apicid : 0
initial apicid : 0
fpu : yes
fpu_exception : yes
cpuid level : 13
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology eagerfpu pn
i pclmulqdq ssse3 cx16 pcid sse4_1 sse4_2 popcnt aes xsave avx hypervisor lahf_lm ssbd ibrs ibpb stibp kaiser xsaveopt
bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass
bogomips : 4399.95
clflush size : 64
cache_alignment : 64
address sizes : 44 bits physical, 48 bits virtual
power management:
メモリ
- 2GBあるな。サンプルアプリなら十分ですね。
# free
total used free shared buff/cache available
Mem: 1963824 818372 129492 19744 1015960 865928
Swap: 1910780 98144 1812636
load average
- 負荷も少なそう。App Service でデプロイした環境って、共有の仮想環境ではないのか。。。
# w
15:51:18 up 3 days, 9:25, 3 users, load average: 0.44, 0.46, 0.49
おわりに
- Azure App Service で Flask と OpenCV を使う方法と動作確認をしました。
- Azure CLI でデプロイが完結出来るのは良いと思いました。
- 今回で、
Heroku
GCP App Engine
AWS Lambda
とAzure App Service
での、Flask と OpenCV の環境構築シリーズは完了です。 - それぞれ、デプロイ用の設定ファイルを準備するだけで、各環境を利用出来ました。アプリ側のコードの修正は、不要でした。まぁ、当たり前かもしれませんが、確認出来たのは良かったかも。
- 本当は、
Azure Functions
を使いたかったのですが、難易度高そうだったので諦めました。 - 次は、各環境で
Keras
とResNet
を使ったサンプルアプリを作ろうかな?と思っております。