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つでした:
-
😱 Docker環境でのホスト名の勘違い
- コンテナ内の「localhost」は外の世界のlocalhostじゃない!
- 別コンテナへの接続には、サービス名を使う必要がある
-
😵 ポート設定の混乱
- DynamoDBのデフォルトポートは8000なのに9000で設定していた
- アプリの接続設定とDocker Composeの設定が食い違っていた
-
🤦♂️ 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」はそのコンテナ自身だけを指す
つまり、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ポートで動いている」と思い込んでいました。しかし実際には:
- コンテナ内のDynamoDBは8000番ポート(デフォルト)で動いていた
- ホスト側からは9000番でアクセスできる状態だった
-
バックエンドコードでは
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
この設定のポイント:
-
FastAPIコンテナは環境変数
DYNAMODB_ENDPOINT
で接続先を設定 - DynamoDBはポート9000で起動、データは永続化
-
サービス間の依存関係を
depends_on
で明示 - 管理コンソールも追加(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
- localhost症候群: コンテナ間通信なのにlocalhostを使ってしまう
- ポート数字だけ合わせ症候群: 「9000:8000」と設定したのに、両方9000と思い込む
- イメージ再ビルド忘れ症候群: 設定ファイル変更後にイメージを再ビルドしない
📚 DynamoDB Localの裏技テクニック
AWS公式ドキュメントには書かれていない便利な設定:
- -port 9000: ポート番号をデフォルト8000から変更(他のサービスと衝突回避に便利)
- -sharedDb: 一つのDBファイルを共有(開発時のデータ一貫性に重要)
- -inMemory: 高速だがデータは永続化されない(テスト時に便利)
- -dbPath: データの保存場所を指定(ボリュームマウントと組み合わせて使おう)
🎓 学びと教訓
-
コンテナ間の通信はサービス名:
localhost
ではなくサービス名
を使おう - 設定は全て一致させる: アプリとDockerの設定で同じ値を使う
- 変更後は常に再ビルド: Dockerイメージは自動更新されない
🏁 まとめ:この知識でもう悩まない!
Docker ComposeでDynamoDB Localを使うときは、ホスト名の指定とポート設定の一貫性が鍵です。そして最後に必ずイメージを再ビルドすることを忘れないでください。
この記事のノウハウを実践すれば、私のような「1時間の苦しみ」を経験せずに済みます。今日からあなたもDocker × DynamoDBマスターです!