この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
CX事業本部@大阪の岩田です。
以下のブログでお伝えしたようにLambdaのパッケージフォーマットとしてコンテナイメージがサポートされるようになりました。
Lambdaの周辺ツールである、SAM CLIが既にコンテナイメージのパッケージに対応していたので、早速SAM CLIを使ってコンテナイメージ作成〜デプロイまで試してみました。
やってみる
SAM CLIのバージョンアップ
まずSAM CLIを最新化しておきましょう。
$pip install --upgrade aws-sam-cli
$sam --version
SAM CLI, version 1.13.1
現時点では1.13.1が最新版でした。
プロジェクトの作成
準備ができたのでsam init
してプロジェクトを初期化します。
$sam init
対話形式で色々と聞かれますが、パッケージ形式に関する選択肢が増えていることが分かります。What package type would you like to use?
の質問に対してImageを意味する2
を入力します。ベースとして使用するイメージはamazon/python3.8-base
を指定しました。このAWS公式イメージにはRICが内包されており、ランタイムAPIとのやりとりをRICにお任せすることができます。
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/nodejs12.x-base
2 - amazon/nodejs10.x-base
3 - amazon/python3.8-base
4 - amazon/python3.7-base
5 - amazon/python3.6-base
6 - amazon/python2.7-base
7 - amazon/ruby2.7-base
8 - amazon/ruby2.5-base
9 - amazon/go1.x-base
10 - amazon/java11-base
11 - amazon/java8.al2-base
12 - amazon/java8-base
13 - amazon/dotnetcore3.1-base
14 - amazon/dotnetcore2.1-base
Base image: 3
Project name [sam-app]: sam-app-with-container-image
Cloning app templates from https://github.com/aws/aws-sam-cli-app-templates
-----------------------
Generating application:
-----------------------
Name: sam-app-with-container-image
Base Image: amazon/python3.8-base
Dependency Manager: pip
Output Directory: .
Next steps can be found in the README file at ./sam-app-with-container-image/README.md
初期化できたらディレクトリを移動します。
$cd sam-app-with-container-image/
ディレクトリの中身を確認してみましょう。
$tree
.
├── README.md
├── __init__.py
├── events
│ └── event.json
├── hello_world
│ ├── Dockerfile
│ ├── __init__.py
│ ├── app.py
│ └── requirements.txt
├── samconfig.toml
├── template.yaml
└── tests
├── __init__.py
└── unit
├── __init__.py
└── test_handler.py
4 directories, 12 files
hello_worldディレクトリ配下にDockerfileが作成されているところが分かります。
Dockerfileの中身は以下の通りでした
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"]
CMD
にLambdaのhandlerとなるファイルと関数が指定されています。
自動生成されたSAMテンプレートを確認してみましょう。
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
python3.8
Sample SAM Template for sam-app-with-container-image
# 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
# ImageConfig:
# Uncomment this to override command here from the Dockerfile
# Command: ["app.lambda_handler"]
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
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
HelloWorldFunctionに設定されているプロパティPackageType
とMetadata
に注目です。それぞれ以下の意味を持ちます。
- PackageType
- パッケージ形式を指定するプロパティで、
Zip
もしくはImage
が指定可能です
- パッケージ形式を指定するプロパティで、
- Metadata
sam build
実行時の振る舞いを制御するためのプロパティで、以下のプロパティが指定可能です- Dockerfile
- Dockerfileのファイル名を指定するプロパティです
- DockerContext
- Dockerfileの場所を指定するプロパティで、指定されたディレクトリがビルドコンテキストとなります
- DockerTag
- ビルドしたイメージに付与するタグを指定するプロパティ
- DockerBuildArgs
- ビルド時の
--build-arg
を指定するプロパティです
- ビルド時の
- Dockerfile
コンテナイメージのビルドとPUSH
続いてコンテナイメージをビルドします。今回は自動生成されたテンプレートから何も変更せずにビルドしてみます。
$sam build
Building codeuri: . runtime: None metadata: {'Dockerfile': 'Dockerfile', 'DockerContext': './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
---> c5a0f0b52673
Step 2/4 : COPY app.py requirements.txt ./
---> eeb7dd5543ff
Step 3/4 : RUN python3.8 -m pip install -r requirements.txt -t .
---> Running in 494d064dbb2a
Collecting requests
Downloading requests-2.25.0-py2.py3-none-any.whl (61 kB)
Collecting certifi>=2017.4.17
Downloading certifi-2020.11.8-py2.py3-none-any.whl (155 kB)
Collecting urllib3<1.27,>=1.21.1
Downloading urllib3-1.26.2-py2.py3-none-any.whl (136 kB)
Collecting idna<3,>=2.5
Downloading idna-2.10-py2.py3-none-any.whl (58 kB)
Collecting chardet<4,>=3.0.2
Downloading chardet-3.0.4-py2.py3-none-any.whl (133 kB)
Installing collected packages: certifi, urllib3, idna, chardet, requests
Successfully installed certifi-2020.11.8 chardet-3.0.4 idna-2.10 requests-2.25.0 urllib3-1.26.2
WARNING: You are using pip version 20.2.1; however, version 20.3 is available.
You should consider upgrading via the '/var/lang/bin/python3.8 -m pip install --upgrade pip' command.
---> d05bfcc30f1e
Step 4/4 : CMD ["app.lambda_handler"]
---> Running in 7370c01ca4aa
---> 942107bcba50
Successfully built 942107bcba50
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
sam build
を実行するとdocker build
まで実行され、コンテナイメージがビルドされていることが分かります。
続いてビルドしたコンテナイメージをECRにPUSHします。このあたりの作業はsam build
やsam deploy
で自動作成されないので、自分で対応する必要があります。
$aws ecr create-repository --repository-name helloworldfunction --image-tag-mutability MUTABLE --image-scanning-configuration scanOnPush=true
{
"repository": {
"repositoryArn": "arn:aws:ecr:ap-northeast-1:<AWSアカウントID>:repository/helloworldfunction",
"registryId": "<AWSアカウントID>",
"repositoryName": "helloworldfunction",
"repositoryUri": "<AWSアカウントID>.dkr.ecr.ap-northeast-1.amazonaws.com/helloworldfunction",
"createdAt": 1606889269.0,
"imageTagMutability": "MUTABLE",
"imageScanningConfiguration": {
"scanOnPush": true
},
"encryptionConfiguration": {
"encryptionType": "AES256"
}
}
}
リポジトリが作成できたらログインします。
$aws ecr get-login-password | docker login --username AWS --password-stdin <AWSアカウントID>.dkr.ecr.ap-northeast-1.amazonaws.com
Login Succeeded
ローカルのイメージにタグを付与してECRにPUSHします
$docker tag helloworldfunction:python3.8-v1 <AWSアカウントID>.dkr.ecr.ap-northeast-1.amazonaws.com/helloworldfunction:python3.8-v1
$docker push <AWSアカウントID>.dkr.ecr.ap-northeast-1.amazonaws.com/helloworldfunction:python3.8-v1
The push refers to repository [<AWSアカウントID>.dkr.ecr.ap-northeast-1.amazonaws.com/helloworldfunction]
b2fd08fab701: Pushed
b3766120b913: Pushed
9b79aa2a550c: Pushed
8089fc755039: Pushed
120614c3628c: Pushed
2c1b97dd87b9: Pushed
57f5bfde13ee: Pushed
af6d16f2417e: Pushed
python3.8-v1: digest: sha256:7c3abe75461f5564951442ceaa267b8c6b282ae41da3f0276f21cdd12e4fe1b4 size: 1999
これで準備完了です
SAM CLIでデプロイする
準備ができたのでデプロイします。対話形式でコンテナイメージのリポジトリを聞かれるので、先程作成したECRのリポジトリのURIを入力します。
$ sam deploy --guided
Configuring SAM deploy
======================
Looking for config file [samconfig.toml] : Not found
Setting default arguments for 'sam deploy'
=========================================
Stack Name [sam-app]: lambda-pkgfmt-container-test
AWS Region [us-east-1]: ap-northeast-1
Image Repository []: <AWSアカウントID>.dkr.ecr.ap-northeast-1.amazonaws.com/helloworldfunction
Images that will be pushed:
helloworldfunction:python3.8-v1 to <AWSアカウントID>.dkr.ecr.ap-northeast-1.amazonaws.com/helloworldfunction:helloworldfunction-942107bcba50-python3.8-v1
#Shows you resources changes to be deployed and require a 'Y' to initiate deploy
Confirm changes before deploy [y/N]: y
#SAM needs permission to be able to create roles to connect to the resources in your template
Allow SAM CLI IAM role creation [Y/n]: y
HelloWorldFunction may not have authorization defined, Is this okay? [y/N]: y
Save arguments to configuration file [Y/n]: y
SAM configuration file [samconfig.toml]:
SAM configuration environment [default]:
Looking for resources needed for deployment: Not found.
Creating the required resources...
Successfully created!
Managed S3 bucket: aws-sam-cli-managed-default-samclisourcebucket-69i44xrx71t3
A different default S3 bucket can be set in samconfig.toml
Saved arguments to config file
Running 'sam deploy' for future deployments will use the parameters saved above.
The above parameters can be changed by modifying samconfig.toml
Learn more about samconfig.toml syntax at
https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-config.html
The push refers to repository [<AWSアカウントID>.dkr.ecr.ap-northeast-1.amazonaws.com/helloworldfunction]
b2fd08fab701: Layer already exists
b3766120b913: Layer already exists
9b79aa2a550c: Layer already exists
8089fc755039: Layer already exists
120614c3628c: Layer already exists
2c1b97dd87b9: Layer already exists
57f5bfde13ee: Layer already exists
af6d16f2417e: Layer already exists
helloworldfunction-942107bcba50-python3.8-v1: digest: sha256:7c3abe75461f5564951442ceaa267b8c6b282ae41da3f0276f21cdd12e4fe1b4 size: 1999
Deploying with following values
===============================
Stack name : lambda-pkgfmt-container-test
Region : ap-northeast-1
Confirm changeset : True
Deployment image repository : <AWSアカウントID>.dkr.ecr.ap-northeast-1.amazonaws.com/helloworldfunction
Deployment s3 bucket : aws-sam-cli-managed-default-samclisourcebucket-69i44xrx71t3
Capabilities : ["CAPABILITY_IAM"]
Parameter overrides : {}
Signing Profiles : {}
Initiating deployment
=====================
HelloWorldFunction may not have authorization defined.
Uploading to lambda-pkgfmt-container-test/614deef9037e9199c68bda82754d59e7.template 1195 / 1195.0 (100.00%)
Waiting for changeset to be created..
CloudFormation stack changeset
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Operation LogicalResourceId ResourceType Replacement
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ Add HelloWorldFunctionHelloWorldPermissionProd AWS::Lambda::Permission N/A
+ Add HelloWorldFunctionRole AWS::IAM::Role N/A
+ Add HelloWorldFunction AWS::Lambda::Function N/A
+ Add ServerlessRestApiDeployment47fc2d5f9d AWS::ApiGateway::Deployment N/A
+ Add ServerlessRestApiProdStage AWS::ApiGateway::Stage N/A
+ Add ServerlessRestApi AWS::ApiGateway::RestApi N/A
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Changeset created successfully. arn:aws:cloudformation:ap-northeast-1:<AWSアカウントID>:changeSet/samcli-deploy1606891016/7f41b30b-38ac-4c48-b65f-b0c76dc19d39
Previewing CloudFormation changeset before deployment
======================================================
Deploy this changeset? [y/N]: y
2020-12-02 15:37:23 - Waiting for stack create/update to complete
CloudFormation events from changeset
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ResourceStatus ResourceType LogicalResourceId ResourceStatusReason
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
CREATE_IN_PROGRESS AWS::IAM::Role HelloWorldFunctionRole -
CREATE_IN_PROGRESS AWS::IAM::Role HelloWorldFunctionRole Resource creation Initiated
CREATE_COMPLETE AWS::IAM::Role HelloWorldFunctionRole -
CREATE_IN_PROGRESS AWS::Lambda::Function HelloWorldFunction -
CREATE_IN_PROGRESS AWS::Lambda::Function HelloWorldFunction Resource creation Initiated
CREATE_COMPLETE AWS::Lambda::Function HelloWorldFunction -
CREATE_IN_PROGRESS AWS::ApiGateway::RestApi ServerlessRestApi Resource creation Initiated
CREATE_IN_PROGRESS AWS::ApiGateway::RestApi ServerlessRestApi -
CREATE_COMPLETE AWS::ApiGateway::RestApi ServerlessRestApi -
CREATE_IN_PROGRESS AWS::Lambda::Permission HelloWorldFunctionHelloWorldPermissionProd Resource creation Initiated
CREATE_IN_PROGRESS AWS::ApiGateway::Deployment ServerlessRestApiDeployment47fc2d5f9d -
CREATE_IN_PROGRESS AWS::Lambda::Permission HelloWorldFunctionHelloWorldPermissionProd -
CREATE_IN_PROGRESS AWS::ApiGateway::Deployment ServerlessRestApiDeployment47fc2d5f9d Resource creation Initiated
CREATE_COMPLETE AWS::ApiGateway::Deployment ServerlessRestApiDeployment47fc2d5f9d -
CREATE_IN_PROGRESS AWS::ApiGateway::Stage ServerlessRestApiProdStage -
CREATE_IN_PROGRESS AWS::ApiGateway::Stage ServerlessRestApiProdStage Resource creation Initiated
CREATE_COMPLETE AWS::ApiGateway::Stage ServerlessRestApiProdStage -
CREATE_COMPLETE AWS::Lambda::Permission HelloWorldFunctionHelloWorldPermissionProd -
CREATE_COMPLETE AWS::CloudFormation::Stack lambda-pkgfmt-container-test -
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
CloudFormation outputs from deployed stack
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Outputs
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Key HelloWorldFunctionIamRole
Description Implicit IAM Role created for Hello World function
Value arn:aws:iam::<AWSアカウントID>:role/lambda-pkgfmt-container-tes-HelloWorldFunctionRole-1PXZX592JZIIW
Key HelloWorldApi
Description API Gateway endpoint URL for Prod stage for Hello World function
Value https://xxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/Prod/hello/
Key HelloWorldFunction
Description Hello World Lambda Function ARN
Value arn:aws:lambda:ap-northeast-1:<AWSアカウントID>:function:lambda-pkgfmt-container-test-HelloWorldFunction-3JMCGF5J66UP
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Successfully created/updated stack - lambda-pkgfmt-container-test in ap-northeast-1
しばらく待つとデプロイ完了です。
デプロイされたLambdaを確認してみましょう。
パッケージ形式:イメージ でデプロイされていることが分かります。
最後に以下のcurlコマンドを実行しAPI GW経由でLambdaを実行してみます。
$curl https://xxxxxx.execute-api.ap-northeast-1.amazonaws.com/Prod/hello/
{"message": "hello world"}
無事にレスポンスが返ってきました。
まとめ
SAM CLIを使ったコンテナイメージの作成とデプロイを試してみました。ツールが対応しているので、とても簡単ですね。コンテナイメージをLambdaにデプロイするためのCI/CDパイプラインの整備なんかもやりやすそうです。SAMユーザーの方はLambdaのパッケージ形式として従来のZIPだけではなく、コンテナイメージという選択肢も検討してみてはいかがでしょうか?