Lambda のコンテナイメージを sam cli で作成&ビルドして実行してみよう

はじめに

Lambda のパッケージとしてコンテナイメージがサポートされました。AWSドキュメントを参照すると、プロジェクトのディレクトリ作成からDockerファイル作成などと設定がたくさんあります。大変そうな印象ですよね。

なんとsam cliでも既にコンテナイメージがサポート済みで、簡単にコンテナイメージのプロジェクト作成からビルド、テスト実行までできるようになっています。

今回は、sam cli でコンテナイメージの Lambda を作成し、動作確認してみましょう。Lambda関数は、Python3.8で作ります。

実施環境

・mac OS(10.14.5)

・sam cli(1.24)

・aws cli(2.0.59)

事前準備

sam cliのインストール手順は前回の記事 に記載していますので、こちらを参照ください。

sam cli 「v1.13.1」 以上からコンテナイメージサポートしているので、バージョンが古ければ最新にアップデートしましょう。

$ brew upgrade aws-sam-cli

$ sam --version
SAM CLI, version 1.24.

コンテナイメージのプロジェクト作成

sam initでプロジェクト作成します。

パッケージタイプに「image」が追加されていますね!

順番に「2: image」、「4: amazon/python3.8-base」、今回動作確認用なので「1: Hello World Lambda Image Example」を選択します。

$ sam init
Which template source would you like to use?
        1 - AWS Quick Start Templates
        2 - Custom Template Location
Choice: 1
What package type would you like to use?
        1 - Zip (artifact is a zip uploaded to S3)
        2 - Image (artifact is an image uploaded to an ECR image repository)
Package type: 2

Which base image would you like to use?
        1 - amazon/nodejs14.x-base
        2 - amazon/nodejs12.x-base
        3 - amazon/nodejs10.x-base
        4 - amazon/python3.8-base
        5 - amazon/python3.7-base
        6 - amazon/python3.6-base
        7 - amazon/python2.7-base
        8 - amazon/ruby2.7-base
        9 - amazon/ruby2.5-base
        10 - amazon/go1.x-base
        11 - amazon/java11-base
        12 - amazon/java8.al2-base
        13 - amazon/java8-base
        14 - amazon/dotnet5.0-base
        15 - amazon/dotnetcore3.1-base
        16 - amazon/dotnetcore2.1-base
Base image: 4

Project name [sam-app]: my_functions

Cloning from https://github.com/aws/aws-sam-cli-app-templates

AWS quick start application templates:
        1 - Hello World Lambda Image Example
        2 - PyTorch Machine Learning Inference API
        3 - Scikit-learn Machine Learning Inference API
        4 - Tensorflow Machine Learning Inference API
        5 - XGBoost Machine Learning Inference API
Template selection: 1

    -----------------------
    Generating application:
    -----------------------
    Name: my_functions
    Base Image: amazon/python3.8-base
    Dependency Manager: pip
    Output Directory: .

    Next steps can be found in the README file at ./my_functions/README.md

Scikit-learnやTensorflowなど機械学習のテンプレートが既にあるんですね!

sam init を実行すると、カレントディレクトリにプロジェクトが作成されます。

hello_world配下にDockerfileができています。

ls -l hello_world
total 24
-rw-r--r--@ 1 xxx  staff   242  6 12 20:10 Dockerfile
-rw-r--r--  1 xxx  staff     0  6 12 20:10 __init__.py
-rw-r--r--@ 1 xxx  staff  1826  5 16 00:57 app.py
-rw-r--r--@ 1 xxx  staff    14  6 12 20:19 requirements.txt

Dockerfileも自動生成してくれるのはありがたいですね。

中身は下記のようになっています。

FROM :python 3.8イメージ(ECRになっていますね)
COPY:Lambda関数ファイル app.py、requirements.txtをイメージへコピー
CMD:Lambdaハンドラー

FROM public.ecr.aws/lambda/python:3.8

COPY app.py requirements.txt ./

RUN python3.8 -m pip install -r requirements.txt -t .

# Command can be overwritten by providing a different command in the template directly.
CMD ["app.lambda_handler"]

Lambda関数作成

前回の記事 で作成したLambda関数を流用しました。

  • template.yaml

中身を見ると PacakeType が「image」、Metadataの箇所も「Dockerfile」になっていますね。

template.yaml に HelloWorldFunction>Properties>Environment に環境変数を追加します。設定内容は前回の記事と同様です。

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
  python3.8

  Sample SAM Template for my_functions

# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
Globals:
  Function:
    Timeout: 3

Resources:
  HelloWorldFunction:
    Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
    Properties:
      PackageType: Image
      Events:
        HelloWorld:
          Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
          Properties:
            Path: /hello
            Method: get
      Environment:
        Variables:
          S3_BUCKET: 'test-bucket'
          S3_PATH: '/sample_data/test.csv'
          SECRET_KEY: 'test_key'
          TZ: 'Asia/Tokyo'
    Metadata:
      Dockerfile: Dockerfile
      DockerContext: ./hello_world
      DockerTag: python3.8-v1

Outputs:
  # ServerlessRestApi is an implicit API created out of Events key under Serverless::Function
  # Find out more about other implicit resources you can reference within SAM
  # https://github.com/awslabs/serverless-application-model/blob/master/docs/internals/generated_resources.rst#api
  HelloWorldApi:
    Description: "API Gateway endpoint URL for Prod stage for Hello World function"
    Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/"
  HelloWorldFunction:
    Description: "Hello World Lambda Function ARN"
    Value: !GetAtt HelloWorldFunction.Arn
  HelloWorldFunctionIamRole:
    Description: "Implicit IAM Role created for Hello World function"
    Value: !GetAtt HelloWorldFunctionRole.Arn
  • requirements.txt
  • テスト用データ

前回の記事と同様です。

ビルド

sam buildを実行すると、docker buildも実行されます。

実行ログ見ると、コンテナイメージのビルドされていますね。

$ sam build --use-container
Starting Build inside a container
Building codeuri: /Users/xxx/jupiter_study/image_test/my_functions runtime: None metadata: {'Dockerfile': 'Dockerfile', 'DockerContext': '/Users/xxx/jupiter_study/image_test/my_functions/hello_world', 'DockerTag': 'python3.8-v1'} functions: ['HelloWorldFunction']
Building image for HelloWorldFunction function
Setting DockerBuildArgs: {} for HelloWorldFunction function
Step 1/4 : FROM public.ecr.aws/lambda/python:3.8
 ---> 7f7dc1f0e633
Step 2/4 : COPY app.py requirements.txt ./
 ---> 6c2b75a7e429
Step 3/4 : RUN python3.8 -m pip install -r requirements.txt -t .
 ---> Running in d370e30aea17
Collecting requests
  Downloading requests-2.25.1-py2.py3-none-any.whl (61 kB)
Collecting boto3
  Downloading boto3-1.17.93-py2.py3-none-any.whl (131 kB)
Collecting certifi>=2017.4.17
  Downloading certifi-2021.5.30-py2.py3-none-any.whl (145 kB)
Collecting urllib3<1.27,>=1.21.1
  Downloading urllib3-1.26.5-py2.py3-none-any.whl (138 kB)
Collecting chardet<5,>=3.0.2
  Downloading chardet-4.0.0-py2.py3-none-any.whl (178 kB)
Collecting idna<3,>=2.5
  Downloading idna-2.10-py2.py3-none-any.whl (58 kB)
Collecting botocore<1.21.0,>=1.20.93
  Downloading botocore-1.20.93-py2.py3-none-any.whl (7.6 MB)
Collecting jmespath<1.0.0,>=0.7.1
  Downloading jmespath-0.10.0-py2.py3-none-any.whl (24 kB)
Collecting s3transfer<0.5.0,>=0.4.0
  Downloading s3transfer-0.4.2-py2.py3-none-any.whl (79 kB)
Collecting python-dateutil<3.0.0,>=2.1
  Downloading python_dateutil-2.8.1-py2.py3-none-any.whl (227 kB)
Collecting six>=1.5
  Downloading six-1.16.0-py2.py3-none-any.whl (11 kB)
Installing collected packages: six, urllib3, python-dateutil, jmespath, botocore, s3transfer, idna, chardet, certifi, requests, boto3
Successfully installed boto3-1.17.93 botocore-1.20.93 certifi-2021.5.30 chardet-4.0.0 idna-2.10 jmespath-0.10.0 python-dateutil-2.8.1 requests-2.25.1 s3transfer-0.4.2 six-1.16.0 urllib3-1.26.5
WARNING: Running pip as root will break packages and permissions. You should install packages reliably by using venv: https://pip.pypa.io/warnings/venv
WARNING: You are using pip version 21.1.1; however, version 21.1.2 is available.
You should consider upgrading via the '/var/lang/bin/python3.8 -m pip install --upgrade pip' command.
 ---> 0e06e91917d7
Step 4/4 : CMD ["app.lambda_handler"]
 ---> Running in ee34c9f68eda
 ---> 2f2ef4fffc19
Successfully built 2f2ef4fffc19
Successfully tagged helloworldfunction:python3.8-v1

Build Succeeded

Built Artifacts  : .aws-sam/build
Built Template   : .aws-sam/build/template.yaml

Commands you can use next
=========================
[*] Invoke Function: sam local invoke
[*] Deploy: sam deploy --guided

Lambda実行

sam cliで作成しているため local invoke で実行できます。

$sam local invoke HelloWorldFunction --docker-network <テスト用のlocalstackネットワークID> --log-file check.log --profile=localstack

いかがでしたでしょうか。sam cliを利用することで簡単にコンテナイメージのLambdaの作成からローカル実行までできました。

参考

SAMビルドドキュメント


--------------------------
システム開発のご要望・ご相談はこちらから

コメントを残す

メールアドレスが公開されることはありません。