概要
Azure App Service に Python (Flask) アプリをデプロイしたときに、RuntimeError: eventlet worker requires eventlet 0.24.1 or higher
のエラーが生じてアプリを起動させることが出来ませんでした。
直面した問題
Webページを開くとApplication Errorが表示されました。ログストリームを確認すると、以下のようなエラーとともにアプリが停止していたことが確認されました。
Traceback (most recent call last):
File "/opt/python/3.10.14/lib/python3.10/site-packages/gunicorn/util.py", line 111, in
mod = importlib.import_module('.'.join(components))
File "/opt/python/3.10.14/lib/python3.10/importlib/__init__.py", line 126, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 688, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 883, in exec_module
File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
File "/opt/python/3.10.14/lib/python3.10/site-packages/gunicorn/workers/geventlet.py", line
raise RuntimeError("eventlet worker requires eventlet 0.24.1 or higher")
RuntimeError: eventlet worker requires eventlet 0.24.1 or higher
このアプリでは、WebサーバーとしてGunicornとEventletを使っています。非同期処理を行うため、この2つを併用する必要がありました。ところが、これらのライブラリが適切にインストールされいないために、このようなエラーが生じたと分かります。
しかし、requirements.txt
は正しく記述できており、単なるバージョンの問題ではありませんでした。
(一部抜粋)
eventlet==0.37.0
gunicorn==23.0.0
解消方法
この問題の背景にあるのは、「必要なライブラリをインストールするPython環境」と「gunicornでアプリを立ち上げるときに使うPython環境」が一致していないことです。
AzureポータルからApp Serviceの管理コンソールを開いて、「設定 > 構成 > 全般設定 > スタートアップコマンド」を以下のように設定します。(設定後5分くらい待つと反映される)
# もともと設定していたこれを消して、
gunicorn --worker-class eventlet -w 1 startup:app
# こっちに変更する
python3.10 -m pip install --upgrade pip && \
python3.10 -m pip install -r requirements.txt && \
python3.10 -m pip list && \
python3.10 -m gunicorn --worker-class eventlet -w 1 startup:app
これにより「pip install
する対象の環境」と「gunicornを呼び出す環境」は、同じものが明確に指定されます。 ここではpython3.10
の環境を使っています。pip list
は無くても大丈夫です。
なお、アプリ起動時にインストールが行われるため、コールドスタートの時間が長くなります。「常時接続(Always on)」をオンにしておくこともオススメします。
備考
上記のように特定のPython環境を指定せず、pip list && gunicorn(以下略)
をスタートアップコマンドとして指定すると、以下のような結果が得られます。Flaskやgunicornの古いバージョンがインストールされており、果たして何を参考にインストールされたものであるかは不明です。
Package Version
-------------------- -------
appsvc-code-profiler 1.0.0
blinker 1.8.2
click 8.1.7
debugpy 1.8.1
distlib 0.3.8
filelock 3.15.2
Flask 3.0.3
gunicorn 22.0.0
itsdangerous 2.2.0
Jinja2 3.1.4
markdown-it-py 3.0.0
MarkupSafe 2.1.5
mdurl 0.1.2
objprint 0.2.3
orjson 3.10.1
packaging 24.1
pip 24.0
platformdirs 4.2.2
psutil 6.0.0
Pygments 2.18.0
rich 13.7.1
setuptools 70.0.0
subprocess32 3.5.4
virtualenv 20.26.2
vizplugins 0.1.3
viztracer 0.15.6
Werkzeug 3.0.3
wheel 0.43.0
まとめ
正直なところ、ライブラリのインストールはApp Service側で自動的に上手いこと行なってくれるものだと思いこんでいました。思わぬ落とし穴でした。