Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

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

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 イメージを落としてきてやればよい。 

hoto17296
ソフトウェアエンジニアです
churadata
沖縄で データ分析 / 機械学習 / Deep Learning をやっている会社です
https://churadata.okinawa/
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