passlibを使うLambdaをWindowsでデプロイしてpasslib.exc.MissingBackendErrorとなったら
先に結論
Windows(WSL)でデプロイ時、Lambdaのアーキテクチャがx86_64だと、bcryptが使用できないというエラーが発生しました。Lambdaのアーキテクチャにarm64を使うと、エラーが発生しなくなりました。
現象
WindowsのWSLを使って開発しています。
passlib経由でbcryptを動かすFunctionを作成して、ローカルでは正しく動作しました。
ただし、Serverless Frameworkでデプロイして、Functionを動かすとpasslib.exc.MissingBackendError: bcrypt: no backends available -- recommend you install one (e.g. 'pip install bcrypt')
というエラーが発生しました。
環境
Windows 11 | バージョン 22H2 (OSビルド 22621.2283) |
CPU | 11th Gen Intel(R) Core(TM) i5-11400H @ 2.70GHz 2.69 GHz |
WSL バージョン | 1.2.5.0 |
カーネル バージョン | 5.15.90.1 |
Ubuntu | 20.04.5 LTS |
serverless | 3.34.0 |
serverless-python-requirements | 6.0.0 |
Python | 3.10 |
Pipenv | 2023.7.11 |
passlib | 1.7.4 |
bcrypt | 4.0.1 |
エラー内容
File "/var/task/app/password.py", line 41, in password
hashed_password = pwd_context.hash(plain_password)
File "/var/task/passlib/context.py", line 2258, in hash
return record.hash(secret, **kwds)
File "/var/task/passlib/utils/handlers.py", line 779, in hash
self.checksum = self._calc_checksum(secret)
File "/var/task/passlib/handlers/bcrypt.py", line 591, in _calc_checksum
self._stub_requires_backend()
File "/var/task/passlib/utils/handlers.py", line 2254, in _stub_requires_backend
cls.set_backend()
File "/var/task/passlib/utils/handlers.py", line 2156, in set_backend
return owner.set_backend(name, dryrun=dryrun)
File "/var/task/passlib/utils/handlers.py", line 2176, in set_backend
raise default_error
passlib.exc.MissingBackendError: bcrypt: no backends available -- recommend you install one (e.g. 'pip install bcrypt')
コード
service: serverless-example
frameworkVersion: '>=3.0.0 <4.0.0'
plugins:
- serverless-python-requirements
custom:
pythonRequirements:
usePipenv: false
pipCmdExtraArgs:
- '--platform'
- 'manylinux2014_x86_64'
- '--only-binary=:all:'
dockerizePip: true
provider:
name: aws
stage: dev
runtime: python3.10
region: ap-northeast-1
iamRoleStatements:
- Effect: Allow
Action:
- ec2:DescribeInstances
Resource: "*"
[packages]
passlib = {version = "*", extras = ["bcrypt"]}
...(略)
-i https://pypi.org/simple
...(略)
bcrypt==4.0.1
passlib[bcrypt]==1.7.4
...(略)
デプロイ方法
$ pipenv requirements > requirements.txt
$ npx sls deploy --aws-profile hoge
調査
requirements.txtにもbcryptモジュールは含まれていました。もちろんLambdaデプロイのためののzipファイルに、bcryptモジュールは含まれていました。なぜ動かないのかわからず。
$ ls serverless-example | egrep 'passlib|bcrypt'
bcrypt
bcrypt-4.0.1.dist-info
passlib
passlib-1.7.4.dist-info
macでデプロイしてLambdaを動かしてみると、エラーが発生しませんでした。なので、使用しているOSによって起こる問題なのかもしれません。
対策
試しにLambdaのアーキテクチャをarm64に変更して再現するのか確認してみたら、エラーが発生しませんでした!もしこのエラーが発生するときはアーキテクチャを変更してもいいかもしれません(arm64の方が処理速度が速いし)
ただ、Pipenvの問題なのか、serverless-python-requirementsのプラグインの問題なのか、それとも別の問題なのか、根本原因はわかりませんでした。x86_64でエラーを回避する方法は見つけられなかったので、もしわかる方がいればコメントお願いします。
arm64に変更したコード
service: serverless-example
frameworkVersion: '>=3.0.0 <4.0.0'
plugins:
- serverless-python-requirements
custom:
pythonRequirements:
usePipenv: false
pipCmdExtraArgs:
- '--platform'
- 'manylinux2014_aarch64'
- '--only-binary=:all:'
dockerizePip: true
provider:
name: aws
architecture: arm64
stage: dev
runtime: python3.10
region: ap-northeast-1
iamRoleStatements:
- Effect: Allow
Action:
- ec2:DescribeInstances
Resource: "*"
参考URL
Discussion