AWS Lambda Layersで Pillow (PIL) を利用しようとした際に、"cannot import _imaging from PIL" というエラーに直面した経験はないだろうか。この問題は、Lambda実行環境とレイヤーのビルド環境の差異に起因することが多い。
本記事では、この問題を解決するための具体的な手順と、筆者の経験に基づく実践的なアドバイスを提供する。
Pillow (PIL) とAWS Lambda Layersの連携における課題
Pillow (PIL) は画像処理ライブラリとして非常に便利だが、ネイティブライブラリに依存しているため、AWS Lambda Layersで利用するには注意が必要だ。Lambdaの実行環境は、レイヤーとしてアップロードされたコードやライブラリとは異なるアーキテクチャやOSで動作する可能性がある。
特に、_imaging モジュールはPillowのコア部分であり、これが正しくビルド・配置されていない場合にインポートエラーが発生する。
現場での具体的なメリット
- 依存関係の分離と管理の容易化: Lambda関数のデプロイパッケージを軽量化し、Pillowのような外部ライブラリをレイヤーとして分離することで、コードの管理と更新が容易になる。
- 開発効率の向上: 複雑な依存関係を持つライブラリもレイヤー化することで、Lambda関数のコード自体はシンプルに保てる。開発者はビジネスロジックに集中すべきだ。
- 実行時間の短縮: レイヤーは初回実行時(コールドスタート)にのみロードされる。関数デプロイパッケージが小さければ、初期ロード時間が短縮され、全体の実行効率が向上する可能性がある。
現場での注意点とハマりどころ
Pillow (PIL) をLambda Layersで利用する際の主なハマりどころは、ビルド環境と実行環境のアーキテクチャの不一致だ。ローカル環境やCloudShellで pip install pillow を実行しても、その環境(例: x86_64)でビルドされたPillowが、Lambdaの実行環境(ARMアーキテクチャの場合など)で期待通りに動作しないことがある。筆者の経験上、このアーキテクチャの不一致が原因でデバッグに時間を費やしたケースは少なくない。
- アーキテクチャの統一: Lambda関数で指定するアーキテクチャ(x86_64またはarm64)と、Pillowをビルドする際のターゲットアーキテクチャを一致させることが必須だ。
- ネイティブ依存関係の解決: Pillowは
libjpegやzlibなどのネイティブライブラリに依存している。これらのライブラリがLambda実行環境に存在しない、またはバージョンが異なる場合、問題が発生する。 - Lambda RuntimeのPythonバージョン: 使用するPythonのバージョン(例: Python 3.11)と互換性のあるPillowのバージョンを選定することが重要だ。
解決策:Dockerを使ったLambda環境でのビルド
最も確実な方法は、Lambdaが実行される環境(またはそれに近い環境)でPillowをビルドし、レイヤーを作成することだ。AWS提供のLambda Runtime Interface Emulator (RIE) を利用したり、Dockerコンテナを使用してLambdaの実行環境をエミュレートしながらビルドするのが一般的だ。これにより、アーキテクチャや依存関係の不一致による問題を回避できる。
以下に、Lambda実行環境をエミュレートしたDockerコンテナ内でのビルド手順を示す。
# 1. Lambda Linux イメージを取得 (例: public.ecr.aws/lambda/python:3.11) # 2. コンテナ内で Pillow をインストール $ docker run -v ".:/var/task" public.ecr.aws/lambda/python:3.11 bash >root $ apt-get update && apt-get install -y libjpeg-dev zlib1g-dev root $ pip install pillow ># 3. Lambda Layer 用のディレクトリ構造を作成し、インストールされたライブラリをコピー # (例: python/lib/python3.11/site-packages/) root $ mkdir -p python/lib/python3.11/site-packages root $ cp -R /usr/local/lib/python3.11/site-packages/* python/lib/python3.11/site-packages/ # 4. python ディレクトリを zip 化し、Lambda Layer としてアップロード root $ cd python root $ zip -r ../pillow_layer.zip . # 5. Lambda 関数側で Python 3.11 ランタイムを使用し、作成した Layer をアタッチ
結論:正しくビルドされたレイヤーでPillowの課題を克服する
AWS Lambda LayersでPillow (PIL) のインポートエラーに遭遇した場合、その原因の多くはビルド環境と実行環境の差異にある。Lambda実行環境をエミュレートした環境(Dockerなど)でPillowをビルドし、必要なネイティブ依存関係も含めてレイヤーを作成することで、この問題を根本的に解決できる。
これにより、Lambda関数での画像処理機能を安定して利用できるようになる。この手順を実行すれば、迷うことはないだろう。

