0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

FastAPI と DynamoDB Local を使った開発環境構築と動作検証ログ

Last updated at Posted at 2025-07-31

はじめに

FastAPI と DynamoDB Local を組み合わせたローカル開発環境を構築し、JWT 認証付きの API 経由で DynamoDB Local にアクセスする構成を検証しました。この記事では、構築手順・疎通確認・実際に発生したエラーと対応策をまとめています。
本番環境では AWS 上の DynamoDB を使用することを前提としつつ、ローカル完結での開発・検証環境として DynamoDB Local を使用しています。
目的は以下の通りです:

  • Docker Compose による FastAPI サーバーと DynamoDB Local の同時起動
  • JWT 認証付きエンドポイントからの DynamoDB 操作確認(CRUD)
  • 各種エンドポイントでのトークンベース認証によるアクセス検証
  • DynamoDB Local との実際のデータ操作(PutItem / GetItem 相当)が行えることの確認
  • 実際に遭遇したエラーとその原因・対処方法の記録

開発環境構成

項目 内容
フレームワーク FastAPI
データベース DynamoDB Local
認証 JWT(パスワード認証+トークン発行)
SDK boto3(AWS SDK for Python)
実行環境 Docker + docker-compose による構築

DynamoDB Local とは?

DynamoDB Local は、AWS の NoSQL データベースである DynamoDB を、ローカル環境で擬似的に動作させるためのソフトウェア(開発用エミュレーター)です。つまり、「DynamoDBにリクエストを送るコードが正しく動くのか」をローカルで検証するための疑似環境です。Docker イメージとして提供されており、AWS アカウントや課金なしで DynamoDB と同様のインターフェースをローカルで再現することができます。

特徴

  • AWS アカウントやインターネット接続なしで動作可能
  • boto3aws-sdkから本番と同様に操作可能
  • -inMemory オプションにより、データをファイルに保存せずメモリ上でのみ軽量に実行可能
  • ユニットテストやローカル開発に適している

DynamoDB との違い

DynamoDB Local はあくまで「開発・検証専用の代替手段」であり、性能については本番環境と異なります。ただし、APIの仕様・リクエスト形式・データ構造は本番と同じであるため、ローカル開発・テスト環境としては実用的です。

DynamoDB DynamoDB Local
実行環境 AWS リージョン上 ローカルマシン or Docker コンテナ
利用目的 本番運用、大規模・高可用アプリケーション 開発・ユニットテスト・CI 実行用
課金 従量課金制 無料
認証 IAM 認証が必要 認証不要(または任意)
保存方式 永続保存(AWS リージョン内に保持) ディスク保存 or メモリオンリー(-inMemory
スケーラビリティ 自動スケーリングに対応 単一ノードでスケーリング不可
SDK 互換性 boto3 / aws-sdk など公式 SDK に対応 本番同様に SDK・API がそのまま使える

実施内容と検証結果

Docker Compose による構成

以下は、FastAPI コンテナと DynamoDB Local コンテナを同時に立ち上げる構成です。

docker-compose.yml
services:
  web:
    build: .
    container_name: fastapi-app
    ports:
      - "8000:8000"
    env_file:
      - .env
    depends_on:
      - dynamodb
    command: uvicorn main:app --host 0.0.0.0 --port 8000 --reload
    environment:
      - PYTHONPATH=/app
    volumes:
      - ./app:/app

  dynamodb:
    image: amazon/dynamodb-local
    container_name: dynamodb-local
    ports:
      - "8001:8000"
    volumes:
      - dynamodb-data:/home/dynamodb
    restart: always

volumes:
  dynamodb-data:

実際に発生したエラーと解決策

ローカルで FastAPI サーバーから DynamoDB Local に接続しようとした際に 実際に遭遇したエラーと対応した内容です。

1. EndpointConnectionError: Could not connect to the endpoint URL

発生タイミング:

  • FastAPI の起動直後、boto3 経由で DynamoDB Local へ接続した際に発生

エラーログ:

botocore.exceptions.EndpointConnectionError: Could not connect to the endpoint URL: "http://localhost:8000"

原因:

  • FastAPI コンテナ内部から、localhost:8000 を参照していたが、これはFastAPI 自身のローカルホストを指しており、DynamoDB Local には到達しない
app/clients/dynamodb.py
修正前
endpoint_url = "http://localhost:8000"

修正後
# Docker Compose の service 名で名前解決されるため、service名を使用
endpoint_url = "http://dynamodb:8000" 

2. ResourceNotFoundException: Requested resource not found

発生タイミング:

  • Admins や PostsなどDynamoDB Local にまだ存在しないテーブルに対して、get_item()scan() などを呼び出した場合に発生

エラーログ:

botocore.errorfactory.ResourceNotFoundException: An error occurred (ResourceNotFoundException) when calling the GetItem operation: Requested resource not found

原因:

  • DynamoDB Local に対象テーブルが存在しない状態で boto3 を通じて操作しようとしたため
  • 具体的には、dynamodb.Table(...).get_item() などを直接呼び出しているが、その前にテーブル作成create_table()や存在確認load()処理を行っていない
utils/dynamodb.py
修正前
import boto3
import os

dynamodb = boto3.resource(
    "dynamodb",
    region_name=os.environ["AWS_REGION"],
    endpoint_url=os.environ["DYNAMODB_ENDPOINT"],
    aws_access_key_id="dummy",
    aws_secret_access_key="dummy"
)

# 存在チェック・作成なしで直接テーブル操作(エラーの原因)
settings_table = dynamodb.Table("SettingsTable")

response = settings_table.get_item(Key={"id": "app_settings"})
item = response.get("Item", {})

修正後
# 以下のコードにより、実行時に SettingsTable が存在しない場合は作成されるように対応
def create_table_if_not_exists(table_name, key_schema, attribute_definitions, billing_mode="PAY_PER_REQUEST"):
    try:
        existing_tables = dynamodb_client.list_tables()["TableNames"]
        if table_name in existing_tables:
            print(f"既にテーブルが存在します: {table_name}")
            return

        dynamodb_client.create_table(
            TableName=table_name,
            KeySchema=key_schema,
            AttributeDefinitions=attribute_definitions,
            BillingMode=billing_mode  # ← ここは明示的に関数引数から渡されている
        )
        print(f"テーブルを作成しました: {table_name}")

    except ClientError as e:
        print(f"DynamoDB操作中にエラーが発生しました: {e.response['Error']['Message']}")
        raise

3. NoCredentialsError: Unable to locate credentials

発生タイミング:

  • FastAPI起動時、bot3経由でDynamoDB Localアクセスした時に発生

エラーログ:

botocore.exceptions.NoCredentialsError: Unable to locate credentials

原因:

  • DynamoDB Local は認証不要だが、boto3 は明示的に認証情報を渡さないと ~/.aws/credentials を参照しようとして失敗する
app/clients/dynamodb.py
修正前
dynamodb = boto3.resource("dynamodb", endpoint_url="http://dynamodb:8000")

修正後
# ダミーの認証情報を明示的に指定することで、解決
dynamodb = boto3.resource(
    "dynamodb",
    endpoint_url="http://dynamodb:8000",
    region_name="ap-northeast-1",
    aws_access_key_id="dummy",
    aws_secret_access_key="dummy"
)

4. Unexpected error: Cannot connect to host dynamodb:8000 ssl:default

発生タイミング:

  • Docker Compose 起動直後、FastAPI が DynamoDB より早く起動してboto3 によるアクセスが行われた場合に発生

エラーログ:

botocore.exceptions.EndpointConnectionError: Could not connect to the endpoint URL: "http://dynamodb:8000"

原因:

  • Docker Compose のdepends_on はコンテナのプロセス起動のみを保証し、アプリケーションが "ready" になることまでは保証しない
  • DynamoDB Local が "listen" 状態になる前に FastAPI 側がリクエストを出してしまった

対応:

  • この問題は現在、utils/dynamodb.py を使用した手動テーブル作成スクリプトで 事前にテーブルが存在する状態を作る ことで回避した
  • リトライロジックを入れて待機させる実装は行っていない

検証で得られた知見

  • DynamoDB Local でも boto3 は明示的な認証情報を要求する
    • 本来 DynamoDB Local では IAM 認証は不要だが、boto3 はデフォルトで ~/.aws/credentials を参照してしまうため、明示的にダミーのアクセスキーを渡す必要がある
    • これは boto3 の仕様上避けられないため、ローカル環境であっても aws_access_key_id / aws_secret_access_key の指定が必須
  • Docker Compose の depends_on は「起動順」だけで「起動完了待ち」にはならない
    • depends_on によって FastAPI より先に DynamoDB Local コンテナは起動するが、DynamoDB 内部のリスナーが listen 状態になるまで待たない
    • そのため、FastAPI 側が即座に boto3 でアクセスを試みると EndpointConnectionError が発生する
    • 根本的な対応には、リトライ処理の追加または 起動前の明示的なテーブル初期化処理が必要

まとめ

FastAPI と DynamoDB Local を組み合わせて、ローカル開発環境を構築し、接続・疎通確認を行いました。この環境は、AWSリソースを使わず、CI/CDやユニットテストの前段階で信頼性のある開発を進めるためのベースとして非常に有用です。

0
1
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
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?