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


紹介する内容

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

結論

  • lambdaのpackageのインストールを別のdockerコンテナにしたら、いろんな言語のpackageインストールに対応できます
    • localstackのコンテナにpythonのvenvなどのバージョン管理ツールをインストールして使う手もあります。ですが、言語ごとにツールの使い方を思えるより、dockerの使い方を覚えて全言語をカバーする方が効率的だと思いました
  • 別のdockerコンテナでterraformをインストールして実行するから、HOSTマシン(MACやwindows)にインストールされているterraformを気にしなくてもいいと思います。

  • localstackのdocker-entrypoint-initaws.dでterraformを使うことで開発環境プロビジョニングするコストが減ります

    • 例えば本番環境用terraformを持っていたら、開発環境用に少し修正してlocalstackですぐ使えます

紹介始めます

localstack紹介

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

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

https://github.com/localstack/localstack

terraform紹介

コードでインフラを管理できます。
https://www.terraform.io/

ディレクトリ構成

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

  • 全体図

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

  • terraformファイルを置く部分

  • 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
      TERRAFORM_PATH: /workspace/terraform
    volumes:
      - ./sam-lambda:/workspace/sam-lambda
      - ./terraform:/workspace/terraform

  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-terraform/sam-lambdaと同じです
    • localstackのdocker-entrypoint-initaws.d機能を使うためにマウントして置きます
      • ./initawsは絶対パスqitta-example/localstack/0.11.0/init-by-terraform/initawsと同じです
  • pip_installerコンテナ

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

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つが連携して作業するから管理しやすくするために設定しました
    • TERRAFORM_PATH はterraformファイルのパスです。terraformコマンド実行するためにterraformファイルがいるところに移動する必要があります。便利な移動のために事前に指定しておきました

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-terraform/initaws00_create_lambda_zip.sh を実行してくれます。
  4. 00_create_lambda_zip.sh

    • 待機していたpip_installerコンテナにdockerコマンドで入ります
    • pythonのpackageをディレクトリqitta-example/localstack/0.11.0/init-by-terraform/sam-lambda/hello_world/packages に指定し、インストールします
    • pythonコード及びインストールしたpackageたちをzipで固めて$LAMBDA_ZIP_PATHに置きます
    • terraformをインストールしあます
    • terraformファイルがいる $TERRAFORM_PATH に移動します
    • terraform initします
    • terraform applyします。同時にterraformでlambdaのzipパス($LAMBDA_ZIP_PATH)を渡します
    • terraformによってlambdaが作られます
    • pip_installerコンテナを終了し、削除します

localstackで作ったlambdaを試します

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

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

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

terraformをインストールします

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

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

terraform initします

lambdaが作られました(terraform apply)

コンソールをもう一個開いて、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-terraform/sam-lambda/hello_world/app.py