LoginSignup
41
36

Mac だけど Python で AWS Lambda したい!

Last updated at Posted at 2017-08-03

この記事の内容は古くて、例えば ARM Mac (Apple Silicon) ではうまくいかなかったりします。とはいえ Docker コンテナをビルドしたり起動したりする際に platform オプションを指定すれば出来るとは思いますが、未確認です。

AWS Lambda が Python 3.6 をサポートしたとのことなので、今まで Node.js で書いていた Lambda Function を Python で書いてみることにしたのだけれど、numpy などの C で書かれたモジュールを含んだ Lambda Function を Mac からデプロイすると 「それは Mac 用にビルドされたモジュールだから読み込めんよ」 などと言われて Lambda 上で実行できないくてつらい。

この問題を Docker で解決したのでその方法についてまとめる。

[2020.03.25 追記] Lambda Layer を作成する方法についても書いた。
Docker で AWS Lambda の Python 用 Layer を作成する - Qiita

デプロイしたい Lambda Function の例

今回は、以下のような numpy を読み込む以外何もしない Lambda Function をデプロイすることを考える。

ディレクトリ構成
.
├── main.py
└── requirements.txt
main.py
import numpy

def handler(event, context):
    pass
requirements.txt
numpy

Mac 上で普通にインストールした場合

以下のコマンドを実行すると同じディレクトリに numpy がインストールされるが、これでインストールされたものを zip に固めてデプロイしても numpy が Mac 用のビルドなので Lambda 上では動かない。

$ pip install -r requirements.txt -t .

たぶんこんなエラーが出るはず。

Unable to import module 'main':
Importing the multiarray numpy extension module failed. Most likely you are trying to import a failed build of numpy.
If you're working with a numpy git repo, try `git clean -xdf` (removes all files not under version control). Otherwise reinstall numpy.

Original error was: cannot import name 'multiarray'

解決策をググると「Amazon Linux インスタンスを立ち上げてそこでビルドする」みたいな謎の回答しか出てこない。AWS Lambda でサーバーレスしたいのにデプロイにサーバが必要とはこれ如何に???

要は Linux 環境でビルドできればいいんじゃ。
それ Docker でできるよ。

Docker コンテナ上でビルドする

先程のコマンドを Docker コンテナ上で実行するには以下のようにすればよい。

$ docker run --rm -v $(pwd):/work -w /work python:3.6 pip install -r requirements.txt -t .

Python 3.6 のイメージ1からコンテナを起動して、作業ディレクトリ /work にカレントディレクトリをマウントして、そこでパッケージをインストールする。ビルドが完了したらもうこのコンテナは不要なので --rm オプションをつけて削除されるようにしている。

これで Linux 環境でビルドされた numpy が手に入ったので、あとはこれを固めてデプロイすれば動くはず。

どうやって開発すればいいか

「Linux 用のモジュールをインストールしてしまったら今度は開発時に Mac 上で実行できないじゃないか」と思うかもしれない。

確かに Mac 上では動かすことはできないが、開発するときも全部 Docker コンテナに乗せて実行すればいいと思う。

$ docker run --rm -v $(pwd):/work -w /work python:3.6 python -c 'import main; main.handler({}, None)'

こんな感じで。

  1. python:3.6 イメージはベースが Debian なので Lambda の実行環境 (Amazon Linux) とは違うのだけど、インストールされたのが numpy-1.13.1-cp36-cp36m-manylinux1_x86_64.whl だったので Linux ならなんでもいいんだと思われる。numpy 以外のモジュールでダメなやつがあるかもしれないが、その場合は Amazon Linux の Docker イメージを落としてきてやればよい。

41
36
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
41
36