LoginSignup
37
29

Docker で AWS Lambda の Python 用 Layer を作成する

Last updated at Posted at 2020-03-24

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

AWS Lambda の Python ランタイムでよく使うモジュールを Lambda Layers に登録しようと思ったが、EC2 インスタンスを立ち上げてパッケージを作るのが面倒なので Docker でできるようにした。

Lambda Layers とは何か

  • ファイルを zip で固めたものをアップロードして「レイヤー」として登録することができる
  • Lambda Function にレイヤーを追加すると、ランタイムの /opt 以下に固めたファイルが展開されて実行時に利用できるになる
  • 言語ごとに指定された名前のディレクトリの中にモジュールを入れておくと、Lambda Function から読み込めるようにパスを通してくれる
    • 例えば Python ランタイムの場合、レイヤー zip 内の python という名前のディレクトリに Python モジュールを入れておくと Lambda Function 側でそのモジュールを import で読み込むことができる

詳しくは: AWS Lambda レイヤー - AWS Lambda

Layer を作成するための Docker イメージを作る

Python 3.8 ランタイムは Amazon Linux 2 で動いているらしい 1 ので、本来であれば Amazon Linux 2 の EC2 インスタンスを立ててその中でレイヤーを作るべきである (別に Linux ならなんでもいいかもしれないが、少なくとも macOS で作ったレイヤーは AWS Lambda では動かない 2 ) のだが、実は Amazon Linux は Docker Hub で公式イメージが配布されている 3 ので、これをベースにして Python 3.8 をインストールした Docker イメージを作ればわざわざ EC2 インスタンスを立てる必要がない。

Dockerfile
FROM amazonlinux:2

ARG PYTHON_VERSION=3.8.7

RUN yum update -y && yum install -y tar gzip make gcc openssl-devel bzip2-devel libffi-devel \
  && curl https://www.python.org/ftp/python/${PYTHON_VERSION}/Python-${PYTHON_VERSION}.tgz | tar xz \
  && cd Python-${PYTHON_VERSION} && ./configure && make && make install \
  && cd - && rm -rf Python-${PYTHON_VERSION}

ADD entrypoint.sh /

RUN yum install -y zip \
  && mkdir /python \
  && chmod +x /entrypoint.sh

ENTRYPOINT ["/entrypoint.sh"]

Entrypoint には pip install して zip で固めるスクリプトを登録しておく。

entrypoint.sh
#!/bin/bash -eu

SRC=/python
DIST=/dist/layer.zip

pip3 install -t ${SRC} $@
rm -f ${DIST}
zip -q -r ${DIST} ${SRC}

イメージをビルドする。

$ docker build . -t bundle-pip-modules-for-aws-lambda-layers:python3.8

イメージ名が長ったらしいが別にここは何でもいい。

Docker イメージを使って Layer を作成する

例えば Pandas が使える Lambda Layer を作成する場合。

$ docker run --rm \
    -v $(pwd):/dist \
    bundle-pip-modules-for-aws-lambda-layers:python3.8 \
        pandas

成功すればカレントディレクトリに layer.zip が作成される。

上の例では直接 pandas を指定したが、イメージ名以降の引数は pip3 install で指定できる引数を全て渡せるので、例えば requirements.txt をマウントした上で -r オプションを指定することで多くのモジュールをまとめて Layer にすることもできる。

$ echo 'pandas' > requirements.txt
$ docker run --rm \
    -v $(pwd)/requirements.txt:/requirements.txt \
    -v $(pwd):/dist \
    bundle-pip-modules-for-aws-lambda-layers:python3.8 \
        -r requirements.txt

Layer を登録する

作成された layer.zip をアップロードする。

image.png

AWSCLI からアップロードする場合はこう。

$ aws lambda publish-layer-version \
    --layer-name pandas \
    --compatible-runtimes python3.8 \
    --zip-file fileb://layer.zip

Layer を使用する

一番簡単な例として、Pandas の読み込み以外は何もしない Lambda Function を作ってみる。

lambda_function.py
import pandas

def lambda_handler(event, context):
    pass

作った Lambda Function に登録した Layer を追加する。

image.png

この Lambda Function を実行してみてエラーが出なければ OK 。

  1. AWS Lambda ランタイム - AWS Lambda

  2. Mac だけど Python で AWS Lambda したい! - Qiita

  3. amazonlinux - Docker Hub

37
29
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
37
29