Help us understand the problem. What is going on with this article?

Azure App Service、FlaskとOpenCVの環境構築

はじめに

  • 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

顔認識アプリ

Dockerfile

  • 元イメージは、ubuntu:18.04 にしました。今回は、Python ですが、Node.js や PHP 等にも流用しやすいと考えたためです。
  • DEBIAN_FRONTEND=noninteractive で、apt-get を非対話形式に出来ますね。
  • PYTHONUNBUFFERED=0 は、App Service で、ログを閲覧する時に有用なものです。例えば、print('Hello, Azure!') など、標準出力が閲覧出来ます。設定しないと、標準エラーしか閲覧出来ない様です。
  • apt-getpython3 に最低限必要なパッケージをインストールします。
  • 次に、OpenCVに必要な libopencv-dev をインストールします。また、pip で opencv-python をインストールします。pip でインストールする理由は、pip パッケージの場合、マルチコアで動作してくれる、最新のバージョンである、などが理由です。
  • そして、Azure のコンパネから ssh 接続するための openssh-server をインストールします。
  • コンパネからの接続は、ユーザー名 root パスワード Docker! ポート 2222 Ciphers aes128-cbc,3des-cbc,aes256-cbc MACs hmac-sha1,hmac-sha1-96 を設定する必要があります。
  • 最後に、CMD で sshサーバーと gunicorn 経由で main.pyapp を起動します。
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

image.png

リソースグループの作成

  • 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 は、既定で無効になっている管理者ユーザーを有効にしています。
  • 最後に usernamepassword を確認します。今回は 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回にします。

image.png

送信画像と結果画像

  • 顔認識に使う画像は、一部界隈ではおなじみの顔画像を使いました。
  • Heroku用アプリ、Google App Engine用アプリ、Lambda用アプリで利用した物と同じです。

ダウンロード.png

ログの確認

  • 今回は、約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 があります。

image.png

image.png

cpu確認

  • Intel(R) Xeon(R) CPU E5-2660 0 @ 2.20GHz が 1個でした。
  • flagsavx があるから、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 LambdaAzure App Service での、Flask と OpenCV の環境構築シリーズは完了です。
  • それぞれ、デプロイ用の設定ファイルを準備するだけで、各環境を利用出来ました。アプリ側のコードの修正は、不要でした。まぁ、当たり前かもしれませんが、確認出来たのは良かったかも。
  • 本当は、Azure Functions を使いたかったのですが、難易度高そうだったので諦めました。
  • 次は、各環境で KerasResNet を使ったサンプルアプリを作ろうかな?と思っております。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away