Closed10

Lambdaにコンテナ形式でデプロイする

元小池元小池
元小池元小池

1. プロジェクトディレクトリ作成

mkdir sample-ecr-lambda
cd sample-ecr-lambda

2. リージョンとアカウントIDを環境変数にセット

REGION="ap-northeast-1"
ACCOUNTID=$(aws sts get-caller-identity --output text --query Account)

3. pythonファイル作成

touch app.py
app.py
import json

def handler(event, context):
    return {
        "statusCode": 200,
        "body": json.dumps(
            {
                "message": "hello world",
            }
        ),
    }
touch Dockerfile

パターン1

FROM public.ecr.aws/lambda/python:3.8
COPY app.py   ./
CMD ["app.handler"]

パターン2

FROM public.ecr.aws/lambda/python:3.8 as build
RUN yum install -y unzip && \
    curl -SL https://chromedriver.storage.googleapis.com/86.0.4240.22/chromedriver_linux64.zip > /tmp/chromedriver.zip && \
    curl -SL https://github.com/adieuadieu/serverless-chrome/releases/download/v1.0.0-57/stable-headless-chromium-amazonlinux-2.zip > /tmp/headless-chromium.zip && \
    unzip /tmp/chromedriver.zip -d /opt/ && \
    unzip /tmp/headless-chromium.zip -d /opt/

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

# driverのバイナリ等を /opt 配下にコピー(lambdaでの処理実行時に /tmp にコピーする)
COPY --from=build /opt/headless-chromium /opt/
COPY --from=build /opt/chromedriver /opt/

RUN yum install -y https://dl.google.com/linux/direct/google-chrome-stable_current_x86_64.rpm
RUN pip install selenium

# lambda実行に必要なコード等
COPY app.py requirements.txt ./

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

ENV DISPLAY=:0.0

CMD ["app.lambda_handler"]

パターン3

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

RUN pip install --upgrade pip && \
    pip install -t ./ selenium

COPY app.py  ./
COPY bin/chromedriver /var/task/bin/
COPY bin/headless-chromium /var/task/bin/

CMD ["app.handler"]
docker build -t func1 .
# func1があるか確認
ls func1
docker images
元小池元小池

4. テスト

docker run --rm -p 9000:8080 func1:latest
# 別のターミナルから
curl -XPOST "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{}'
# docker runしたターミナルで
Ctrl+C

5. ECRリポジトリ作成・イメージPUSH

# ECRリポジトリ作成CFn
touch createECRRepository.yaml
AWSTemplateFormatVersion: "2010-09-09"
Description: Create ECR Stack Test

Resources:
  ########################################################
  ### ECR Repository
  ########################################################
  TestEcrPoc:
    Type: AWS::ECR::Repository
    Properties:
      RepositoryName: func1
aws cloudformation create-stack --stack-name tempecrrepo --template-body file://createECRRepository.yaml --region ${REGION}
# 認証
aws ecr get-login-password --region ${REGION} | docker login --username AWS --password-stdin ${ACCOUNTID}.dkr.ecr.${REGION}.amazonaws.com
# イメージPUSH
docker push ${ACCOUNTID}.dkr.ecr.${REGION}.amazonaws.com/func1:latest
元小池元小池

6. Lambda作成

# Lambda作るCFn
touch createLambda.yaml
AWSTemplateFormatVersion: "2010-09-09"
Description: Create ECR Stack Test

Parameters:
  LambdaFunctionName:
    Type: String
  ImageUri:
    Type: String
    
Resources:
  ########################################################
  ### Log Group
  ########################################################
  FunctionLogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: !Sub "/aws/lambda/${LambdaFunctionName}"
      RetentionInDays: 3653

  ########################################################
  ### IAM Role
  ########################################################
  FunctionRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub "for-lambdafunction-${LambdaFunctionName}"
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - 'sts:AssumeRole'
      Path: '/service-role/'
      Policies:
        # CloudWatch
        - PolicyName: write-cloudwatchlogs
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action: 
                  - 'logs:CreateLogStream'
                  - 'logs:PutLogEvents'
                Resource: !Sub "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/${LambdaFunctionName}:*"    

  ########################################################
  ### Lambda Function
  ########################################################
  TargetFunction:
    Type: AWS::Lambda::Function
    Properties:
      FunctionName: !Ref LambdaFunctionName
      Role: !GetAtt FunctionRole.Arn
      PackageType: Image
      Code:
        ImageUri: !Ref ImageUri
# CFnのパラメータに使う文字列を生成
DIGEST=$(aws ecr list-images --repository-name func1 --region ${REGION} --out text --query 'imageIds[?imageTag==`latest`].imageDigest')
IMAGEURI=${ACCOUNTID}.dkr.ecr.${REGION}.amazonaws.com/func1@${DIGEST}

# Lambda作成。IAM作るのでcapabilities指定
aws cloudformation create-stack --stack-name tempecrlambda \
  --template-body file://createLambda.yaml \
  --region ${REGION}  \
  --parameters \
    ParameterKey=LambdaFunctionName,ParameterValue=func1-container \
    ParameterKey=ImageUri,ParameterValue=${IMAGEURI} \
  --capabilities CAPABILITY_NAMED_IAM

# 実行
aws lambda invoke --function-name func1-container --region ${REGION} output ; cat output
元小池元小池

7. 後処理

# Lambda削除
aws cloudformation delete-stack --stack-name tempecrlambda --region ${REGION}

# ECR上イメージ削除
aws ecr batch-delete-image --repository-name func1 --region ${REGION} --image-ids imageDigest=${DIGEST}

# ECRリポジトリ削除
aws cloudformation delete-stack --stack-name tempecrrepo --region ${REGION}

# Dockerイメージを確認して、削除
docker images | grep func1
docker rmi <<IMAGENAME>>
元小池元小池

dockerを使用しなくても、良さそうなので一旦クローズ。

このスクラップは2023/01/04にクローズされました