AWS Lambda で Pillow を使おうとしたらハマった
2019-06-22TL;DR
Lamnbda のデプロイパッケージに含める Pillow のライブラリ群は、 Amazon Linux 2 でインストールしたものを使用する。
Pillow に限らず、Lambda 関数に外部パッケージ (ライブラリ) を含める場合は、 OS 依存の有無に注意が必要。
何がしたかったのか
やりたかったこと
S3 に保存してある画像に対して、 S3 Batch Operations で Lambda を呼んでリサイズをする。
割とよくあるオペレーションだと思うんですが、調べてみると Node.js でやってるパターンばかりで Python でやってるパターンが見つけられませんでした。なので、リサイズ処理用の Lambda 関数は Python で実装してみることにしました。
ランタイムは Python 3.7 にします。
やったこと
Python での画像処理には Pillow を使うと楽なので、今回も Pillow を使うことにします。
Lambda の Python 実行環境には Pillow は存在しないので、ローカルでインストールしたライブラリ群をデプロイパッケージとして zip ファイルにまとめて Lambda にアップロードする必要があります。
Pillow は pip でインストールします。
$ pip3 install Pillow -t dist/
デプロイパッケージにはメインの python ファイルも含めます。
dist
├── PIL
├── Pillow-6.0.0.dist-info
└── lambda_function.py
上記のようなフォルダを zip 化して Lambda にアップロードします。
起こったこと
いざアップロードした関数を実行してみると、次のようなエラーが出ました。
[ERROR] Runtime.ImportModuleError: Unable to import module 'lambda_function': cannot import name '_imaging' from 'PIL' (/var/task/PIL/__init__.py)
ローカル環境では起こっていなかったエラーです。
解決するまでの流れ
色々試してみる
解決するまでに確認・試したことは次のようなことです。
- ローカルと Lambda のランタイムの Python バージョンを合わせる
- Python 3.6 でやってみる
これでは解決しませんでした。
調べてみると、どうやら Pillow のライブラリ群にはインストールする OS に依存する部分があることがわかりました。ということは、 Lambda が実行される環境と同じ環境でインストールした Pillow が必要ということにあります。
Lambda の実行環境
上記ページにもあるように、 Lambda の実行環境 (OS) は Amazon Linux です。なので、 Amazon Linux 上でインストールした Pillow が必要になります。
Amazon Linux 上でインストールした Pillow の取得
シンプルというか、まず思い浮かべるのは Amazon Linux の EC2 インスタンスを立てて、そこでインストールした Pillow を使う方法です。
ただ、これだけのために EC2 インスタンスを立てるのは面倒で、且つ多少なりとも料金が発生してしまいます。
ここで使うのが Docker ですね。 ドッカードッカー言われてもう結構経ちますが、まだほとんど触ったことがなかったので良い機会になりました。
Amazon Linux の docker イメージは dockerhub で公開されているので、それを使います。
やりたいことは以下の通りです。
- Python 3.7 をインストールした Amazon Linux のコンテナを作成する
- Amazon Linux コンテナ内で、ホストと同期したディレクトリに Pillow をインストールする
です。
Dockerfile
と docker-compose.yml
は次のような感じです。
FROM amazonlinux:latest
RUN yum install python3 -y
RUN mkdir /home/deploy
version: '2'
services:
app:
build: .
volumes:
- './deploy:/home/deploy'
command: pip3 install -r /home/deploy/requirements.txt -t /home/deploy/dist
これを下記のようなディレクトリ構成にして docker-compose up --build
を実行すると、 dist
ディレクトリに Amazon Linux 環境でインストールした Pillow のライブラリが保存されます。 (というか同期してるのでここにインストールされる)
.
├── Dockerfile
├── deploy
│ ├── dist
│ └── requirements.txt
└── docker-compose.yml
あとは、ライブラリ群と Python ファイルを zip 化してアップロードすれば ok です。
無事に Lambda で Pillow が使えた
AWS Lambda で Pillow を使おうとしたらハマった話でした。なんとか無事に Pillow を使うことができました。
そして S3 Batch Operations で数万件の画像が一瞬でリサイズされて、すげーってなってました。
今後はデプロイパッケージに含める外部ライブラリについては、 OS 依存の有無に限らず Amazon Linux 環境でインストールしたものを使うようにしたいと思います。
実際にできあがっものは GitHub に置いています。
comments powered by Disqus