AWS Lambdaで外部ライブラリをimportするのに詰まったお話と解決策

みなさん、こんにちは せしょうです!

今回は、AWS Lambda(ラムダ)を使って遊んでみたら、色々と落とし穴があったというお話です。


事の発端は、私がAWS Lambdaを使って遊ぶ際にLayerなるものを使いたくなったことが始まりです。

LayerをAWS Lambdaの関数に追加することが出来るらしい。

 ⇨ ライブラリをLayerに入れれば、使いまわせて便利!!

と思ったわけで、とりあえずLayerを追加したんですが、

  •  そんなライブラリ、パッケージは存在しないよ!! 

  •  OSが違うから使えないよ !

色々と罠があって、盛大にハマってしまったのでその解消法を含め、この記事で共有出来たらなと思います。

よろしくお願いします。

AWS Lambdaとは?

 AWS Lambdaは、サーバーレスのサービスです。中でもAWS Lambdaは GCPのCloud Functionsと同様に常にインスタンスが立ち上がっているわけではなく、何かしら実行するためのトリガーが起動したときにのみ、動くため コスト的にも優しいものとなっています。

 しかし実行時間 などに制限があるため、簡単なツールなどに向いています。

例) Amazon S3(Amazon Simple Storage Service)に画像をアップロードした際に、その画像のサイズをリサイズする

目標

AWS lambdaでOS依存のパッケージをLayerにアップロードしライブラリを使えるようにするための環境を作成し、AWS Lambdaのレイヤーにアップロードする。

パッケージの中には(Pillow、 MeCab等)、OS依存のパッケージがある.

それらを,AWS LambdaのLayerにアップロードして、AWS Lambdaの関数でライブラリをimportすることを目標とする.

目次

  1. ディレクトリ構造

  2. Dockerfile, docker-compose.ymlの中身

  3. requirement.txtにインストールしたいライブラリ名を記述する

  4. コンテナを立ち上げて実行する

  5. AWS Lambdaのレイヤーにzip化したファイルをアップロードする

  6. AWS Lambdaの関数を作成

  7. AWS Lambdaの関数で追加したレイヤーのライブラリをimportする方法

  8. まとめ

ディレクトリ構造

python-package-aws-lambda

├── Dockerfile

├── layers

│   └─- file.zip  ⇦ コンテナを立ち上げることで作成される(今回の目的)

│   └── requirements.txt

└── docker-compose.yml

dockerfile、docker-compose.ymlの中身

今回はコンテナを立ち上げることによって、必要なライブラリのインストールとそのインストールしたライブラリを zipファイルに圧縮するような動きをしています。


ポイントとしては、2点あります。

  1. requirements.txtに指定したライブラリは、pythonディレクトリ配下にインストールされる

  2. Dockerfileの元のイメージが amazonlinux:2であるということ


requirements.txtに指定したライブラリは、pythonディレクトリ配下にインストールされる

AWS Lambdaで、ライブラリをimport するとき、 /python配下にライブラリがないとパスが通っておらず、importできないと言われるため それも対応できるようにしました。

(毎回、関数側で パスを通すという作業するのも面倒くさいので)

※公式ドキュメント:Lambdaレイヤーの作成と共有(ライブラリの依存関係をレイヤーに含める)を参照


Dockerfileの元のイメージが amazonlinux:2であるということ

ライブラリの中には、OSに依存したものがある。

そのため、AWS Lambdaの関数内と同じ環境で、ライブラリをインストールする必要がある。

AWS Lambdaの関数で使用されているOSは amazonlinux2と同様の環境であるため、Dockerfileでは

FROM amazonlinux:latest

をしています。

※公式ドキュメント:Lambdaランタイムを参照


Dockerfile

FROM amazonlinux:latest

 

RUN yum install python3.8 -y zip

RUN mkdir /home/layers

RUN mkdir /home/python

docker-compose.yml

version: '3'

services:

  aws-lambda-layers:

    build: .

    volumes:

      - './layers:/home/layers'

    working_dir: '/home/'

    command: sh -c "python3 -m pip install -r layers/requirements.txt -t python/ && zip -r layers/file.zip python/"

requirement.txtにインストールしたいライブラリ名を記述する

例1) 自然言語処理をしたい人の例

boto3==version

mecab-python3==version

ipadic==version


例2) 画像処理をしたい人の例

boto3==version

Pillow==version

※ ==version : 使いたいライブラリのバージョンを指定

コンテナを立ち上げて実行する

$ docker-compose up --build

⇨ zipファイルが作成される


zipファイルの中身。 python配下に作成されている。

※公式ドキュメント:Lambdaレイヤーの作成と共有(ライブラリの依存関係をレイヤーに含める)を参照

python/boto3/dynamodb/__init__.py

python/boto3/s3/

python/boto3/s3/inject.py

python/boto3/s3/__pycache__/

python/boto3/s3/__pycache__/__init__.cpython-37.pyc

python/boto3/s3/__pycache__/transfer.cpython-37.pyc

python/boto3/s3/__pycache__/inject.cpython-37.pyc

… 


目標のディレクトリ構造になっている

python-package-aws-lambda

├── Dockerfile

├── layers

│   └─- file.zip  ⇦ コンテナを立ち上げることで作成される(今回の目的)

│   └── requirements.txt

└── docker-compose.yml

AWS Lambdaのレイヤーにzip化したファイルをアップロードする

  1. AWS Lambdaを開く
  2. 下記のイメージのように「レイヤー」を選択する
    1. 下記の画像のように、「レイヤーの作成」を選択する

  3. 下記のオプションを参考にレイヤーを作成する
  4. ・名前(必須)

    ・説明-オプション(任意)

    ・zip ファイルをアップロード

      アップロード(5.で作成したzipファイルを選択する.)

    ・ランタイム

      以下のURLを参考にして,使用するランタイムを設定する.

      https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/lambda-runtimes.html

    ここでは,python3.8をランタイムにする.


AWS Lambdaの関数を作成
  1. 下記の画像のように、「関数の作成」を選択する
  2. 下記のオプションを参考に関数を作成する
  3. ・名前(必須)

    ・ランタイム(必須)

      以下のURLを参考にして,使用するランタイムを設定する.

      https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/lambda-runtimes.html

       ここでは,python3.8をランタイムにする.

    ・他デフォルトとする

  4. 作成すると、以下の画像のように作成した関数が開く
  5. 上記のサイトを下にスクロールしていくと、レイヤーの追加が出来るカラムが出てくる
  6. 下記のオプションを参考にレイヤーを追加する
  7. ・レイヤーソース:カスタムレイヤー

    ・カスタムレイヤー: 先ほど作成したレイヤーを選択する

      ここでは、function-package を選択

    ・バージョン : 1 (レイヤーを初めて作成した場合は、バージョン1のみ存在する)

AWS Lambdaの関数で追加したレイヤーのライブラリをimportする方法

通常の使い方と同じ

例1) Mecabを使用するとき

import MeCab


例2) PILを使用するとき

from PIL import Image

まとめ

本日は、AWS Lambdaに触って遊んでみたら、色々と詰まってしまった部分があったので、その解消方法について書かせていただきました。

  • /python ディレクトリ配下でないといけない

  • ライブラリがOSに依存する

など詰まる部分がいくつもあったので、ただ遊ぶだけでも仕様を理解する必要があるんだなと痛感しました。 この記事が誰かの学びの一助になると嬉しいです。

ここまで読んでいただき、ありがとうございます!

また、次回の記事でお会いしましょう。