0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Dev Container で作る AWS Lambda ローカル開発環境 — SAM CLI との組み合わせ完全ガイド

0
Posted at

はじめに

Lambdaの開発で「ローカルで動いたのに本番で動かない」「チームメンバーの環境では再現しない」という経験はないでしょうか。

その根本原因の多くは開発環境の差異にあります。Lambdaはランタイムバージョン・環境変数・IAMロールなど依存する要素が多く、ローカル環境を本番に近づけることが難しいです。

Dev Containerはこの問題を一気に解決します。.devcontainerの設定ファイルをリポジトリに含めるだけで、チーム全員が同一の開発環境をDockerコンテナ上に再現できます。SAM CLIと組み合わせることで、Lambda関数をクラウドにデプロイせずにローカルで呼び出し・デバッグできる開発体験が得られます。

本記事では、Dev Container + SAM CLIによるLambdaローカル開発環境の構築から実際の開発フローまでを解説します。


前提条件

以下がインストール済みであることを確認してください。

  • Docker Desktop(またはDocker Engine + Docker CLI)
  • Visual Studio Code
  • Dev Containers拡張機能ms-vscode-remote.remote-containers

AWS CLIやSAM CLIはコンテナ内にインストールするため、ホストマシンには不要です。


.devcontainerの構成

プロジェクトルートに.devcontainer/ディレクトリを作成し、以下の2ファイルを配置します。

your-lambda-project/
├── .devcontainer/
│   ├── devcontainer.json
│   └── Dockerfile
├── src/
│   └── handler.py
├── template.yaml
└── ...

Dockerfile

FROM public.ecr.aws/amazonlinux/amazonlinux:2023

# 基本ツールのインストール
RUN dnf install -y \
    python3.12 \
    python3.12-pip \
    python3-pip \
    git \
    curl \
    unzip \
    make \
    tar \
    gzip \
    && dnf clean all

# AWS CLI v2 のインストール
RUN curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" \
    && unzip awscliv2.zip \
    && ./aws/install \
    && rm -rf aws awscliv2.zip

# AWS SAM CLI のインストール
RUN curl -Lo sam-installer.zip "https://github.com/aws/aws-sam-cli/releases/latest/download/aws-sam-cli-linux-x86_64.zip" \
    && unzip sam-installer.zip -d sam-installation \
    && ./sam-installation/install \
    && rm -rf sam-installation sam-installer.zip

# 非rootユーザーの作成
RUN useradd -ms /bin/bash vscode
USER vscode
WORKDIR /workspace

ポイント: ベースイメージにamazonlinux:2023を使うことで、Lambdaの実行環境(Amazon Linux 2023ベース)と最も近い環境が手元に揃います。

devcontainer.json

{
  "name": "Lambda Dev",
  "build": {
    "dockerfile": "Dockerfile",
    "context": ".."
  },
  "runArgs": [
    "--privileged"
  ],
  "mounts": [
    "source=/var/run/docker.sock,target=/var/run/docker.sock,type=bind"
  ],
  "workspaceFolder": "/workspace",
  "workspaceMount": "source=${localWorkspaceFolder},target=/workspace,type=bind",
  "customizations": {
    "vscode": {
      "extensions": [
        "amazonwebservices.aws-toolkit-vscode",
        "ms-python.python",
        "ms-python.vscode-pylance",
        "amazonwebservices.amazon-q-vscode"
      ],
      "settings": {
        "python.defaultInterpreterPath": "/usr/bin/python3.12",
        "editor.formatOnSave": true
      }
    }
  },
  "postCreateCommand": "pip3 install --user -r requirements-dev.txt 2>/dev/null || true",
  "remoteUser": "vscode"
}

重要: docker.sockのマウントはSAM CLIがLambda実行用のDockerコンテナを起動するために必要です。Dev Container内からDocker(Docker-in-DockerではなくDocker-outside-of-Docker)を使う形になります。


SAMテンプレートとLambda関数

template.yaml

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Lambda local dev example

Globals:
  Function:
    Timeout: 30
    MemorySize: 256
    Runtime: python3.12
    Environment:
      Variables:
        LOG_LEVEL: DEBUG

Resources:
  HelloFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: src/
      Handler: handler.lambda_handler
      Events:
        ApiEvent:
          Type: Api
          Properties:
            Path: /hello
            Method: get

src/handler.py

import json
import logging
import os

logger = logging.getLogger()
logger.setLevel(os.environ.get("LOG_LEVEL", "INFO"))


def lambda_handler(event, context):
    logger.debug("Received event: %s", json.dumps(event))

    name = event.get("queryStringParameters", {}) or {}
    name = name.get("name", "World")

    return {
        "statusCode": 200,
        "headers": {"Content-Type": "application/json"},
        "body": json.dumps({"message": f"Hello, {name}!"}),
    }

SAM CLIによるローカル実行

Dev Containerを開いたターミナルで以下のコマンドを使います。

ビルド

sam build

--use-containerを付けるとLambdaのランタイムコンテナ内でビルドされ、ネイティブ拡張を含む依存ライブラリも正しく解決されます。

sam build --use-container

単発呼び出し(sam local invoke)

# JSONファイルでイベントを渡す
sam local invoke HelloFunction --event events/hello.json

# 標準入力から渡す
echo '{"queryStringParameters": {"name": "Yudai"}}' | sam local invoke HelloFunction

API Gatewayのローカルエミュレーション

sam local start-api --port 3000

別ターミナルからcurlで叩けます。

curl "http://localhost:3000/hello?name=Yudai"
# => {"message": "Hello, Yudai!"}

Lambdaエンドポイントのエミュレーション

AWS SDKから直接Lambdaを呼び出すテストをしたい場合はstart-lambdaを使います。

sam local start-lambda --port 3001
import boto3

client = boto3.client(
    "lambda",
    endpoint_url="http://localhost:3001",
    region_name="us-east-1",
    aws_access_key_id="dummy",
    aws_secret_access_key="dummy",
)

response = client.invoke(
    FunctionName="HelloFunction",
    Payload=b'{"queryStringParameters": {"name": "test"}}',
)
print(response["Payload"].read())

実際の開発フロー

Dev Containerを使った日常の開発サイクルはシンプルです。

  1. VS Codeでリポジトリを開く → 「Reopen in Container」でコンテナ起動
  2. src/handler.pyを編集
  3. sam buildでビルド(初回は数分、2回目以降はキャッシュが効いて速い)
  4. sam local invokeまたはsam local start-apiで動作確認
  5. ユニットテストもpytest src/tests/でコンテナ内で完結
  6. 問題なければsam deployで本番環境へ
# 初回デプロイ(設定ファイルを生成)
sam deploy --guided

# 2回目以降
sam deploy

ホットリロードを効かせる

sam local start-api--warm-containers EAGERオプションを付けると、コンテナを事前起動して呼び出しのレイテンシを下げられます。ただし変更を反映させるには都度sam buildが必要です。

コードの変更を即座に反映したい場合はsam sync --watchで変更を自動検知・デプロイできます(クラウドへのsyncですが、差分デプロイなので高速)。


まとめ

手法 メリット デメリット
Dev Container + SAM CLI 環境差異ゼロ・チーム共有簡単 初期セットアップに数十分
ローカルに直接SAM CLIインストール すぐ始められる チーム間で差異が出やすい
LocalStack 周辺サービス(S3/DynamoDB等)も含めてエミュレート Pro プランが必要な機能あり

Dev Containerを一度セットアップしてしまえば、git clone → 「Reopen in Container」だけで誰でも同じ環境を手に入れられます。特にチーム開発・CI連携を見据えると、この投資は早い段階で回収できます。

Lambdaのローカル開発に課題を感じていたら、ぜひ試してみてください。


参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?