はじめに
Azure Functions で、Python&OpenCV を使うためのメモです。
# 夜中の変なテンションで書き始めたので、所々おかしい部分があるかもしれません。
いきなり結論
カスタム コンテナー を使いましょう。
苦難の道のり
今回のゴールは、
import cv2
これが通ることです。最初のハードルは低く。
検証する関数コードは、HTTP トリガーのテンプレートに、上記の import 文を追加しただけのコードです。
なお、requirements.txt に記載する OpenCV 関連のモジュールは、opencv-contrib-python
です。
Azure Functions Core Tools から普通にデプロイ
ここに書かれているやり方です。
コマンドはこちら。
$ func azure functionapp publish <APP_NAME> --build remote
デプロイした後に、HTTP トリガーを実行してみると、、、
Result: Failure Exception: ImportError: libgthread-2.0.so.0: cannot open shared object file: No such file or directory Stack: File "/usr/local/lib/python3.6/site-packages/azure_functions_worker/dispatcher.py", line 239, in _handle__function_load_request func_request.metadata.entry_point) File "/usr/local/lib/python3.6/site-packages/azure_functions_worker/loader.py", line 66, in load_function mod = importlib.import_module(fullmodname) File "/usr/local/lib/python3.6/importlib/__init__.py", line 126, in import_module return _bootstrap._gcd_import(name[level:], package, level) File "<frozen importlib._bootstrap>", line 994, in _gcd_import File "<frozen importlib._bootstrap>", line 971, in _find_and_load File "<frozen importlib._bootstrap>", line 941, in _find_and_load_unlocked File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed File "<frozen importlib._bootstrap>", line 994, in _gcd_import File "<frozen importlib._bootstrap>", line 971, in _find_and_load File "<frozen importlib._bootstrap>", line 955, in _find_and_load_unlocked File "<frozen importlib._bootstrap>", line 665, in _load_unlocked File "<frozen importlib._bootstrap_external>", line 678, in exec_module File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed File "/home/site/wwwroot/HttpTrigger/__init__.py", line 4, in <module> import cv2 File "/home/site/wwwroot/.python_packages/lib/python3.6/site-packages/cv2/__init__.py", line 3, in <module> from .cv2 import *
見事に、import cv2 でエラーが出ます。
libgthread-2.0.so.0
が無い、と怒られています。
OpenCV の利用に必要なんでしょうか。
Azure Functions Core Tools からバイナリーパッケージと一緒にデプロイ
libgthread-2.0.so.0 opencv
でググると一発目に出てくる、こちらの Qiita のページに書いてありました。
qiita.com
このエラーは、opencv-python自体はpipでインストールされておりcv2は見つかったものの、依存関係にある外部ライブラリが見つからないというエラーになります。
同じページによると、libopencv-dev
を実行環境に入れてやればよさげ。
Azure Functions Core Tools のこちらの オプションを試してみます。
--additional-packages ネイティブの依存関係を構築するときにインストールするパッケージの一覧。 (例: python3-dev libevent-dev)。
こんな感じでしょうか。
$ func azure functionapp publish <APP_NAME> --additional-packages "libopencv-dev" --build-native-deps
なにやら、ローカルの docker が動き、docker コンテナー内で apt-get install
して、ファイルをローカルにコピーするようです。
Getting site publishing info... Running 'docker pull mcr.microsoft.com/azure-functions/python:2.0.12493-python3.6-buildenv'....done Running 'docker exec -t 02bc71 apt-get update'........done Running 'docker exec -t 02bc71 apt-get install -y libopencv-dev'.................................................................................................done Running 'docker exec -t 02bc71 chmod +x /python_docker_build.sh'...done Running 'docker exec -t 02bc71 /python_docker_build.sh'.................done Running 'docker cp 02bc71:"/.python_packages/." "C:\cases\119062826001861\function1\.python_packages"'...............done Running 'docker kill 02bc71'....done Running 'docker exec -t f2f597 chmod +x /ziptofs.sh'...done Running 'docker exec -t f2f597 /ziptofs.sh'........................done Running 'docker cp f2f597:"/file.squashfs" "C:\Users\hihorika\AppData\Local\Temp\tmpA3DE.tmp"'.....done Running 'docker kill f2f597'....done Uploading package... Uploading 54.82 MB [##############################################################################] Upload completed successfully. Deployment completed successfully.
イケる予感。。。
。。。。。。
だったのですが、同じエラーです。
やっぱり、libgthread-2.0.so.0
が見つかりません。
Result: Failure Exception: ImportError: libgthread-2.0.so.0: cannot open shared object file: No such file or directory Stack: File "/usr/local/lib/python3.6/site-packages/azure_functions_worker/dispatcher.py", line 239, in _handle__function_load_request : File "/home/site/wwwroot/HttpTrigger/__init__.py", line 4, in <module> import cv2 File "/home/site/wwwroot/.python_packages/lib/python3.6/site-packages/cv2/__init__.py", line 3, in <module> from .cv2 import *
どうやら、既定のコンテナーではライブラリーが足りないようです。
カスタム コンテナーで実行環境と関数コードをまとめてデプロイ
最後の手段です。
実行する関数コードと libopencv-dev
をインストールしたコンテナー イメージを作成して、丸ごとデプロイします。
コンテナーを使う場合の手順は、下記のドキュメント全てが書いてあります。
ただし python の関数を作成する時には --python
をつけないと、テンプレートの作成ができませんでした。
Azure Functions Core Tools は最新バージョンを使っているつもりなんですが。。。
func new --name MyHttpTrigger --template "HttpTrigger" --python
Dockerfile
Dockerfile は、テンプレートをベースに、libopencv-dev
をインストールするよう apt update | upgrade | install
等のコマンドを追記して、docker build でイメージを作成します。
FROM mcr.microsoft.com/azure-functions/python:2.0 ENV AzureWebJobsScriptRoot=/home/site/wwwroot \ AzureFunctionsJobHost__Logging__Console__IsEnabled=true COPY . /home/site/wwwroot RUN apt update && \ apt upgrade -y && \ apt install -y libopencv-dev && \ cd /home/site/wwwroot && \ pip install -r requirements.txt
作ったイメージは Docker Hub / Azure Container Registry 等のコンテナー レジストリーに push しておきます。
Function App をデプロイ
あとはドキュメント通りに黙々と、
- ストレージ アカウント
- App Service プラン
- Function App
をデプロイし、以下のアプリケーション設定 (環境変数) を 2 つほど設定するだけです。
- AzureWebJobsDashboard
- AzureWebJobsStorage
実行してみると、import cv2
は無事通過できました。
この後、OpenCV のモジュールが動作するかは試していませんが、最初の (超低空な) ハードルはクリア、ということで。
おまけ
各リソースのデプロイは、Azure ポータルからもデプロイできます。
でもデプロイした後に、上の 2 つのアプリケーション設定のうち片方 (どっちか忘れた) しか設定されていなかったので、手動で作成して値をコピーしたら動きました。