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

【1時間ハマった】Docker × DynamoDB Local接続エラー完全攻略ガイド

Posted at

TL;DR: Docker環境でDynamoDB Localに接続できない?それはlocalhostとポート設定が原因かも!サービス名を使ってhttp://dynamodb-local:9000に接続し、イメージを必ず再ビルドしよう!

🔥 はじめに:私がハマった悪夢のような1時間

「あれ?なんでつながらないんだ...」

シンプルなDocker ComposeでFastAPIとDynamoDB Localを動かそうとしただけなのに、なぜか接続エラーの嵐。公式ドキュメントを見ても解決せず、StackOverflowを彷徨い、数時間を無駄にした経験はありませんか?

私は1時間もこの問題にハマりました。

この記事では、多くの開発者が陥る「Docker ComposeでのDynamoDB Local接続エラー」を完全に解決する方法をお伝えします。この記事を読めば、あなたは同じ苦しみを味わわずに済むでしょう!

💥 発生した問題:謎の「Connection refused」エラー

まず、こんなエラーが出ました:

# 1回目のエラー
botocore.exceptions.EndpointConnectionError: Could not connect to the endpoint URL: "http://localhost:9000/"

# いろいろ試した後の2回目のエラー
botocore.exceptions.EndpointConnectionError: Could not connect to the endpoint URL: "http://dynamodb-local:8000/"

「おかしい...設定は間違ってないはずなのに...」

DynamoDBのコンテナは正常に起動しているのに、なぜかバックエンドアプリからの接続だけが失敗する。この状況に頭を抱えました。

🔍 原因分析:犯人はこの3つだった!

苦しい試行錯誤の末に発見した問題の本質は以下の3つでした:

  1. 😱 Docker環境でのホスト名の勘違い

    • コンテナ内の「localhost」は外の世界のlocalhostじゃない!
    • 別コンテナへの接続には、サービス名を使う必要がある
  2. 😵 ポート設定の混乱

    • DynamoDBのデフォルトポートは8000なのに9000で設定していた
    • アプリの接続設定とDocker Composeの設定が食い違っていた
  3. 🤦‍♂️ Docker Composeの理解不足

    • "9000:8000"の意味は「ホストの9000をコンテナの8000に接続」

これらの問題が複合的に絡み合って、謎のエラーを引き起こしていたのです!

🏠 「localhost」の罠:コンテナ化で一変する世界

「ローカル環境ではバッチリ動いていたのに、Dockerに移したら動かない...」

これが私の最初の困惑でした。コンテナ化する前は、以下のコードで問題なく動作していたのです:

# ローカル環境では問題なく動いていたコード
dynamodb = boto3.resource(
    'dynamodb',
    endpoint_url='http://localhost:9000',  # ローカルでは正しい
    region_name='us-west-2',
    aws_access_key_id='dummy',
    aws_secret_access_key='dummy'
)

しかし、Dockerコンテナに移行した途端、同じコードが動かなくなりました。なぜでしょうか?

「localhost」の意味が変わる!

答えは明快です:コンテナの世界では「localhost」の意味が変わるのです。

  • コンテナ化前:「localhost」はあなたのPC全体を指す
  • コンテナ化後:「localhost」はそのコンテナ自身だけを指す

image.png

つまり、FastAPIコンテナ内の「localhost」はFastAPIコンテナ自身を指し、DynamoDBコンテナを指していないのです。これは、ネットワークの世界観が一変することを意味します。

複数コンテナ環境でのlocalhostの混乱

Docker Compose環境では、各コンテナは独立したネットワーク空間を持ちます:

コンテナA内のlocalhost ≠ コンテナB内のlocalhost ≠ ホストPCのlocalhost

そのため、コンテナ間で通信する場合は「localhost」ではなく、Docker Composeで定義したサービス名を使う必要があるのです。

ポートマッピングとlocalhostの二重の罠

私の場合、localhostの問題ポートマッピングの誤解が重なり、さらに混乱が深まりました:

接続先がlocalhost:9000(間違い)× DynamoDBが8000ポートで動作(勘違い)= 二重の罠

🔄 ポートマッピングの大誤解:私の初期設定の致命的ミス

問題の核心はポートマッピングの誤解でした。初期の設定では以下のようになっていました:

# 🚫 最初の間違った設定
dynamodb-local:
  image: amazon/dynamodb-local
  ports:
    - "9000:8000"  # ホストの9000をコンテナの8000に転送
  command: "-jar DynamoDBLocal.jar -sharedDb -dbPath /home/dynamodblocal/data/"  # ポート指定なし!

私は9000:8000の設定で「DynamoDBが9000ポートで動いている」と思い込んでいました。しかし実際には:

  1. コンテナ内のDynamoDBは8000番ポート(デフォルト)で動いていた
  2. ホスト側からは9000番でアクセスできる状態だった
  3. バックエンドコードではhttp://dynamodb-local:9000に接続しようとしていた

つまり、ポートのミスマッチが発生!コンテナ内では8000番で待ち受けているのに、9000番に接続しようとしていたのです。

Docker Composeのポート設定を正しく理解する

Docker Composeのports設定は以下のフォーマットです:

"ホスト側のポート:コンテナ側のポート"
  • 左側:あなたのPCからアクセスする際のポート番号
  • 右側:コンテナ内のアプリが実際に待ち受けているポート番号

重要なのは、この設定だけではコンテナ内のアプリのポートは変わらないということ。アプリ自体のポートを変更するには、明示的にコマンドオプションで指定する必要があります。

解決策:2つのアプローチ

アプローチ1: DynamoDBのポートを9000に変更(推奨)

# ✅ 推奨解決策
dynamodb-local:
  image: amazon/dynamodb-local
  ports:
    - "9000:9000"  # ホストもコンテナも同じポート
  command: "-jar DynamoDBLocal.jar -sharedDb -port 9000 -dbPath /home/dynamodblocal/data/"  # ここが重要!

アプローチ2: アプリの接続先を8000に変更

# 別の解決策:バックエンドコードを変える
dynamodb = boto3.resource(
    'dynamodb',
    endpoint_url='http://dynamodb-local:8000',  # 8000ポートに接続
    # 以下略
)

どちらの方法でも解決できますが、全ての設定で同じポート番号を使う方がシンプルで混乱が少ないため、アプローチ1をおすすめします。

📄 FastAPI + DynamoDB Local の完全なdocker-compose.yml例

ここでは、FastAPIとDynamoDB Localを連携させるための完全なdocker-compose.yml例を示します:

version: "3"

services:
  # FastAPIバックエンドアプリ
  app:
    container_name: FastAPI
    build: ./backend
    ports:
      - "8000:80"  # ホストの8000をコンテナの80にマッピング
    depends_on:
      - dynamodb-local  # DynamoDBが先に起動するのを保証
    environment:
      - AWS_ACCESS_KEY_ID=dummy
      - AWS_SECRET_ACCESS_KEY=dummy
      - AWS_REGION=us-west-2
      - DYNAMODB_ENDPOINT=http://dynamodb-local:9000  # 重要:サービス名で接続
    
  # フロントエンド(必要に応じて)
  frontend:
    container_name: NextJS
    build: ./frontend
    ports:
      - "3000:3000"
    depends_on:
      - app
  
  # DynamoDB Local
  dynamodb-local:
    image: amazon/dynamodb-local
    container_name: DynamoDB
    ports:
      - "9000:9000"  # ホストの9000をコンテナの9000にマッピング
    command: "-jar DynamoDBLocal.jar -sharedDb -port 9000 -dbPath /home/dynamodblocal/data/"
    volumes:
      - "./dynamodb_data:/home/dynamodblocal/data"  # データの永続化
  
  # DynamoDB管理コンソール(オプション)
  dynamodb-admin:
    image: aaronshaf/dynamodb-admin
    container_name: DynamoAdmin
    ports:
      - "8001:8001"
    environment:
      - DYNAMO_ENDPOINT=http://dynamodb-local:9000
    depends_on:
      - dynamodb-local

この設定のポイント:

  1. FastAPIコンテナは環境変数DYNAMODB_ENDPOINTで接続先を設定
  2. DynamoDBはポート9000で起動、データは永続化
  3. サービス間の依存関係depends_onで明示
  4. 管理コンソールも追加(UI操作できて便利)

これをプロジェクト直下にdocker-compose.ymlとして保存し、以下のコマンドで起動するだけです:

docker compose up -d

✅ 解決方法:これで100%解決!

1️⃣ DynamoDBポートを9000に統一する

DynamoDBのポートはデフォルトで8000ですが、9000に変更して統一するのがシンプル:

dynamodb-local:
  image: amazon/dynamodb-local
  ports:
    - "9000:9000" # ホストの9000をコンテナの9000にマッピング
  command: "-jar DynamoDBLocal.jar -sharedDb -port 9000 -dbPath /home/dynamodblocal/data/"
  volumes:
    - "./dynamodb_data:/home/dynamodblocal/data"

2️⃣ アプリケーションの接続設定を修正

# ❌ 間違い:localhostを使っている
dynamodb = boto3.resource(
    'dynamodb',
    endpoint_url='http://localhost:9000',  # これだとコンテナ自身を指してしまう!
    # 以下略
)

# ✅ 正解:サービス名を使う
dynamodb = boto3.resource(
    'dynamodb',
    endpoint_url='http://dynamodb-local:9000',  # Docker Composeのサービス名
    region_name='us-west-2',
    aws_access_key_id='dummy',
    aws_secret_access_key='dummy'
)

3️⃣ 最も重要!イメージの再ビルド

これを忘れると全ての努力が水の泡に!

# これが超重要!
docker compose down && docker compose build app && docker compose up -d

「え、こんなことだけ?」 と思われるかもしれませんが、実際にこれだけのことで1時間も悩んでいました。ドキュメントには書かれていない実践的なノウハウです。

💡 Docker環境での通信:理解すれば簡単だった

Docker Composeの世界では:

  • localhost = 「自分自身」というコンテナの島
  • サービス名 = 「別のコンテナ島」への橋

この基本概念を忘れると、必ず接続エラーに悩まされることになります!

🔮 よくある間違いトップ3

  1. localhost症候群: コンテナ間通信なのにlocalhostを使ってしまう
  2. ポート数字だけ合わせ症候群: 「9000:8000」と設定したのに、両方9000と思い込む
  3. イメージ再ビルド忘れ症候群: 設定ファイル変更後にイメージを再ビルドしない

📚 DynamoDB Localの裏技テクニック

AWS公式ドキュメントには書かれていない便利な設定:

  • -port 9000: ポート番号をデフォルト8000から変更(他のサービスと衝突回避に便利)
  • -sharedDb: 一つのDBファイルを共有(開発時のデータ一貫性に重要)
  • -inMemory: 高速だがデータは永続化されない(テスト時に便利)
  • -dbPath: データの保存場所を指定(ボリュームマウントと組み合わせて使おう)

🎓 学びと教訓

  1. コンテナ間の通信はサービス名: localhostではなくサービス名を使おう
  2. 設定は全て一致させる: アプリとDockerの設定で同じ値を使う
  3. 変更後は常に再ビルド: Dockerイメージは自動更新されない

🏁 まとめ:この知識でもう悩まない!

Docker ComposeでDynamoDB Localを使うときは、ホスト名の指定ポート設定の一貫性が鍵です。そして最後に必ずイメージを再ビルドすることを忘れないでください。

この記事のノウハウを実践すれば、私のような「1時間の苦しみ」を経験せずに済みます。今日からあなたもDocker × DynamoDBマスターです!

👍 この記事が役に立ったらシェアしてください!

📖 参考文献

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