localstackにLambdaのパッケージをディレクトリ指定でインストールしてzipに固めて作る(pythonバージョン)


紹介する内容

  • localstackでlambdaを作ります
    • localstackのdocker-entrypoint-initaws.dを使う。主にpythonを使います
    • ユーザーが指定したディレクトリにpackageをインストールします
    • インストールしたpackageをzipに固めます

結論

  • lambdaのpackageのインストールを別のdockerコンテナにしたら、いろんな言語のpackageインストールに対応できます

    • localstackのコンテナにpythonのvenvなどのバージョン管理ツールをインストールして使う手もあります。ですが、言語ごとにツールの使い方を思えるより、dockerの使い方を覚えて全言語をカバーする方が効率的だと思いました
  • localstackのdocker-entrypoint-initaws.dでpythonを使うことで二つ以上のリソースが連携する構築が可能です

    • 例えばDynamoDBを生成して、戻り値のARNを使ってlambdaのcreate_event_source_mappingで使用可能です
    • shell scriptなら、戻り値を処理することがややこしくなります

紹介始めます

localstack紹介

実のAWSを使わずにいろいろ試せるものです。

バージョン0.11.0から大きな変化がありました。本記事は0.11.0バージョンのlocalstackを使います

https://github.com/localstack/localstack

ディレクトリ構成

全体ソースコードは https://github.com/cheekykorkind/qiita-example/tree/master/localstack/0.11.0/init-by-py で確認できます

  • 全体図

  • AWS SAMプロジェクトで生成した部分

  • localstackのdocker-entrypoint-initaws.d機能を使うためにマウントした部分

localstack構築

docker composeを使います。

version: '3'

services:
  pip_installer:
    container_name: 'pip_installer'
    image: python:3.7-alpine3.10
    tty: true
    working_dir: /workspace/sam-lambda
    environment:
      LAMBDA_ZIP_PATH: /workspace/sam-lambda/hello_world/lambda.zip
    volumes:
      - ./sam-lambda:/workspace/sam-lambda

  localstack:
    container_name: 'localstack-dev'
    image: localstack/localstack:0.11.0
    ports:
      - '4566:4566'
    environment:
      SERVICES: lambda,logs,dynamodb
      DEBUG: 1
      HOSTNAME_EXTERNAL: localstack
      EDGE_PORT: 4566
      PORT_WEB_UI: 8080

      AWS_ACCESS_KEY_ID: AKIAIOSFODNN7EXAMPLE
      AWS_SECRET_ACCESS_KEY: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
      AWS_DEFAULT_REGION: us-east-1
      LAMBDA_ZIP_PATH: /workspace/sam-lambda/hello_world/lambda.zip
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ./initaws:/docker-entrypoint-initaws.d
      - ./tmp/localstack:/tmp/localstack

      - ./sam-lambda:/workspace/sam-lambda
    depends_on:
      - pip_installer

docker-composeのvolumes(マウント)設定

  • localstackコンテナ

    • packageインストールやzipファイル共有するために、AWS SAMプロジェクトをマウントしておきます。
      • ./sam-lambdaは絶対パスqitta-example/localstack/0.11.0/init-by-py/sam-lambdaと同じです
    • localstackのdocker-entrypoint-initaws.d機能を使うためにマウントして置きます
      • ./initawsは絶対パスqitta-example/localstack/0.11.0/init-by-py/initawsと同じです
  • pip_installerコンテナ

    • packageインストールやzipファイル共有するために、AWS SAMプロジェクトをマウントしておきます。
      • ./sam-lambdaは絶対パスqitta-example/localstack/0.11.0/init-by-py/sam-lambdaと同じです

docker-composeの環境変数設定

  • localstackコンテナ

    • SERVICESDEBUGHOSTNAME_EXTERNALEDGE_PORTPORT_WEB_UI はlocalstack固有の環境変数です。localstackを調べると理解できると思います
    • AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEYAWS_DEFAULT_REGION はaws cliを便利に使うために設定しました
    • LAMBDA_ZIP_PATH はlambda生成に使うzipファイルの位置を書きました。コンテナ2つが連携して作業するから管理しやすくするために設定しました
  • pip_installerコンテナ

    • LAMBDA_ZIP_PATH はlambda生成に使うzipファイルの位置を書きました。コンテナ2つが連携して作業するから管理しやすくするために設定しました

docker-compose upによる作業の流れ

  1. pip_installerコンテナが作れる

    • localstackコンテナがdepends_onしているから、localstackコンテナより先に作られます
    • tty: trueオプションによって、作れた後もup状態を維持します
  2. localstackコンテナが作れる

    • コンテナが作れた後、localstack固有のもろもろ初期化作業が行われます
  3. docker-entrypoint-initaws.dディレクトリにあるshファイルを名前順で実行します

    • localstackの固有機能です。
    • もろもろ初期化作業が終わったら、マウントしている qitta-example/localstack/0.11.0/init-by-py/initaws00_create_lambda_zip.sh01_lambda.sh順で実行してくれます。shではない lambda_create.py は無視されます。
  4. 00_create_lambda_zip.sh

    • 待機していたpip_installerコンテナにdockerコマンドで入ります
    • pythonのpackageをディレクトリqitta-example/localstack/0.11.0/init-by-py/sam-lambda/hello_world/packages に指定し、インストールします
    • pythonコード及びインストールしたpackageたちをzipで固めて$LAMBDA_ZIP_PATHに置きます
    • pip_installerコンテナを終了し、削除します
  5. 01_lambda.sh

    • python /docker-entrypoint-initaws.d/lambda_create.pyを実行されるためのファイルです。
    • docker-entrypoint-initaws.dはshだけ実行するから、書き方が踏み台のようになりました。
    • lambda_create.pyがlambdaを作ります

localstackで作ったlambdaを試します

docker-compose up -d && docker attach localstack-dev します

cd qitta-example/localstack/0.11.0/init-by-py
docker-compose up -d && docker attach localstack-dev

docker attach localstack-devしているあからlocalstackコンテナの作業が見れます

pythonのpackageがpipによってインストールされてます

インストール終了後、zipで固めてます

lambdaが生成されました

コンソールをもう一個開いて、localstackのlambdaにinvokeします

左側が docker attach localstack-dev している方、右側が docker exec -it localstack-dev /bin/bash してlambdaをinvokeする方です。
200返すことからちゃんと動いた確認が取れました。

lambdaのコードはrequestsパッケージを使ってGET一回投げることをしています。
qitta-example/localstack/0.11.0/init-by-py/sam-lambda/hello_world/app.py