[{"data":1,"prerenderedAt":833},["ShallowReactive",2],{"article-aws-sam-disconnect-dymamodb-local":3},{"id":4,"title":5,"body":6,"category":817,"createdAt":819,"description":820,"extension":821,"index":822,"meta":823,"navigation":91,"path":824,"publish":91,"seo":825,"series":822,"seriesTitle":822,"stem":826,"tag":827,"thumbnail":831,"updatedAt":819,"__hash__":832},"articles\u002Farticles\u002Faws-sam-disconnect-dymamodb-local.md","AWS SAMで作ったLamdaコードがローカルのDynamoDBに接続できないときの対処",{"type":7,"value":8,"toc":810},"minimark",[9,13,16,27,30,41,44,47,52,55,220,231,570,573,579,582,589,592,595,600,608,623,626,630,633,751,754,760,766,800,803,806],[10,11,12],"p",{},"こんにちはjunです。最近はこの静的ブログに動的な機能を追加するために、サーバーレス環境でのサービス開発を行っています。API gateway をトリガーとしてAWS Lambdaでコードを実行してDynamoDBで内容を保存するといったよくある構成で開発をしていました。",[10,14,15],{},"AWS Lambdaはweb上でもコードを書いて実行できますが、できたらローカル上でコードを書いてテストしてからデプロイしたいです。特に更新や改修の時はローカルで検証できることが好ましいです。",[10,17,18,19,26],{},"AWSはその辺も考えており、",[20,21,25],"a",{"href":22,"rel":23},"https:\u002F\u002Fdocs.aws.amazon.com\u002Fja_jp\u002Fserverless-application-model\u002Flatest\u002Fdeveloperguide\u002Fwhat-is-sam.html",[24],"nofollow","AWS SAM(serverless application model)"," を用意してくれています。私も開発ではこのSAMを使用してローカルで構築後、テストして本番に適用しています。",[10,28,29],{},"ひとまずチュートリアルのデプロイができたので、DynamoDBを用いた環境をローカルに作ってコードをテストすることにしました。しかし、DynamoDBをscanする処理でいつもストップし、",[31,32,37],"pre",{"className":33,"code":35,"language":36},[34],"language-text","Inaccessible host: `127.0.0.1' at port `8000'. This service may not be available in the `ap-north-east1' region.\n","text",[38,39,35],"code",{"__ignoreMap":40},"",[10,42,43],{},"というメッセージでDynamoDBに接続できませんでした。ちなみにDynamoDBの環境はDockerを用いてローカルで構築しており、localost:8000に待機していました。DynamoDBのコンテナは起動しているのに、どうして接続できないのか悩んでいました。",[10,45,46],{},"結論を言うとDockerのネットワークの設定が間違っていたからです。詳細を解説します。",[48,49,51],"h2",{"id":50},"lambdaのコードとdynamodbのコンテナ設定","LambdaのコードとDynamoDBのコンテナ設定",[10,53,54],{},"DynamoDBはこちらのDocker imageを使用して、以下の設定を用いていました。（参考サイトからのコピペです...)",[31,56,61],{"className":57,"code":58,"filename":59,"language":60,"meta":40,"style":40},"language-yaml shiki shiki-themes material-theme-ocean","version: \"3\"\n\nservices:\n  dynamodb-local:\n    container_name: dynamodb-local\n    image: amazon\u002Fdynamodb-local\n    ports:\n      - 8000:8000\n    command: -jar DynamoDBLocal.jar -dbPath \u002Fdata -sharedDb\n    volumes:\n      - .\u002Fdata:\u002Fdata\n    networks:\n      - lambda-local\nnetworks:\n  lambda-local:\n    external: true\n","docker-compose.yml","yaml",[38,62,63,86,93,102,110,121,132,140,149,160,168,176,184,192,200,208],{"__ignoreMap":40},[64,65,68,72,76,79,83],"span",{"class":66,"line":67},"line",1,[64,69,71],{"class":70},"s-wAU","version",[64,73,75],{"class":74},"sAklC",":",[64,77,78],{"class":74}," \"",[64,80,82],{"class":81},"sfyAc","3",[64,84,85],{"class":74},"\"\n",[64,87,89],{"class":66,"line":88},2,[64,90,92],{"emptyLinePlaceholder":91},true,"\n",[64,94,96,99],{"class":66,"line":95},3,[64,97,98],{"class":70},"services",[64,100,101],{"class":74},":\n",[64,103,105,108],{"class":66,"line":104},4,[64,106,107],{"class":70},"  dynamodb-local",[64,109,101],{"class":74},[64,111,113,116,118],{"class":66,"line":112},5,[64,114,115],{"class":70},"    container_name",[64,117,75],{"class":74},[64,119,120],{"class":81}," dynamodb-local\n",[64,122,124,127,129],{"class":66,"line":123},6,[64,125,126],{"class":70},"    image",[64,128,75],{"class":74},[64,130,131],{"class":81}," amazon\u002Fdynamodb-local\n",[64,133,135,138],{"class":66,"line":134},7,[64,136,137],{"class":70},"    ports",[64,139,101],{"class":74},[64,141,143,146],{"class":66,"line":142},8,[64,144,145],{"class":74},"      -",[64,147,148],{"class":81}," 8000:8000\n",[64,150,152,155,157],{"class":66,"line":151},9,[64,153,154],{"class":70},"    command",[64,156,75],{"class":74},[64,158,159],{"class":81}," -jar DynamoDBLocal.jar -dbPath \u002Fdata -sharedDb\n",[64,161,163,166],{"class":66,"line":162},10,[64,164,165],{"class":70},"    volumes",[64,167,101],{"class":74},[64,169,171,173],{"class":66,"line":170},11,[64,172,145],{"class":74},[64,174,175],{"class":81}," .\u002Fdata:\u002Fdata\n",[64,177,179,182],{"class":66,"line":178},12,[64,180,181],{"class":70},"    networks",[64,183,101],{"class":74},[64,185,187,189],{"class":66,"line":186},13,[64,188,145],{"class":74},[64,190,191],{"class":81}," lambda-local\n",[64,193,195,198],{"class":66,"line":194},14,[64,196,197],{"class":70},"networks",[64,199,101],{"class":74},[64,201,203,206],{"class":66,"line":202},15,[64,204,205],{"class":70},"  lambda-local",[64,207,101],{"class":74},[64,209,211,214,216],{"class":66,"line":210},16,[64,212,213],{"class":70},"    external",[64,215,75],{"class":74},[64,217,219],{"class":218},"sbqyR"," true\n",[10,221,222,223,226,227,230],{},"上記の",[38,224,225],{},"- 8000:8000"," の通りlocalhostの8000にDynamoDBのエンドポイントが待機しています。\n",[38,228,229],{},"docker-compose up","してこの記述の通り、Lambdaのコードで以下のように記述しました。",[31,232,237],{"className":233,"code":234,"filename":235,"language":236,"meta":40,"style":40},"language-js shiki shiki-themes material-theme-ocean","const AWS = require('aws-sdk')\nlet response;\n\nvar dynamoOpt = {\n    endpoint: \"http:\u002F\u002Flocalhost:8000\",\n};\n\nexports.lambdaHandler = async (event, context) => {\n    let params = {\n            TableName:'table',\n        };\n\n        try{\n            const result = await dynamodb.scan(params).promise()\n            return {\n                statusCode: 200,\n                body: JSON.stringify(result.Items),\n            };\n        }catch (e){\n            return {\n                statusCode: 500,\n                body: e.message,\n            };\n        }\n}\n","app.js","js",[38,238,239,270,281,285,298,316,321,325,360,372,388,393,397,406,443,450,463,493,499,517,524,536,553,558,564],{"__ignoreMap":40},[64,240,241,245,249,252,256,259,262,265,267],{"class":66,"line":67},[64,242,244],{"class":243},"sJ14y","const",[64,246,248],{"class":247},"s0W1g"," AWS ",[64,250,251],{"class":74},"=",[64,253,255],{"class":254},"sdLwU"," require",[64,257,258],{"class":247},"(",[64,260,261],{"class":74},"'",[64,263,264],{"class":81},"aws-sdk",[64,266,261],{"class":74},[64,268,269],{"class":247},")\n",[64,271,272,275,278],{"class":66,"line":88},[64,273,274],{"class":243},"let",[64,276,277],{"class":247}," response",[64,279,280],{"class":74},";\n",[64,282,283],{"class":66,"line":95},[64,284,92],{"emptyLinePlaceholder":91},[64,286,287,290,293,295],{"class":66,"line":104},[64,288,289],{"class":243},"var",[64,291,292],{"class":247}," dynamoOpt ",[64,294,251],{"class":74},[64,296,297],{"class":74}," {\n",[64,299,300,303,305,307,310,313],{"class":66,"line":112},[64,301,302],{"class":70},"    endpoint",[64,304,75],{"class":74},[64,306,78],{"class":74},[64,308,309],{"class":81},"http:\u002F\u002Flocalhost:8000",[64,311,312],{"class":74},"\"",[64,314,315],{"class":74},",\n",[64,317,318],{"class":66,"line":123},[64,319,320],{"class":74},"};\n",[64,322,323],{"class":66,"line":134},[64,324,92],{"emptyLinePlaceholder":91},[64,326,327,330,333,336,339,342,346,349,352,355,358],{"class":66,"line":142},[64,328,329],{"class":74},"exports.",[64,331,332],{"class":254},"lambdaHandler",[64,334,335],{"class":74}," =",[64,337,338],{"class":243}," async",[64,340,341],{"class":74}," (",[64,343,345],{"class":344},"s7ZW3","event",[64,347,348],{"class":74},",",[64,350,351],{"class":344}," context",[64,353,354],{"class":74},")",[64,356,357],{"class":243}," =>",[64,359,297],{"class":74},[64,361,362,365,368,370],{"class":66,"line":151},[64,363,364],{"class":243},"    let",[64,366,367],{"class":247}," params",[64,369,335],{"class":74},[64,371,297],{"class":74},[64,373,374,377,379,381,384,386],{"class":66,"line":162},[64,375,376],{"class":70},"            TableName",[64,378,75],{"class":74},[64,380,261],{"class":74},[64,382,383],{"class":81},"table",[64,385,261],{"class":74},[64,387,315],{"class":74},[64,389,390],{"class":66,"line":170},[64,391,392],{"class":74},"        };\n",[64,394,395],{"class":66,"line":178},[64,396,92],{"emptyLinePlaceholder":91},[64,398,399,403],{"class":66,"line":186},[64,400,402],{"class":401},"s6cf3","        try",[64,404,405],{"class":74},"{\n",[64,407,408,411,414,416,419,422,425,428,430,433,435,437,440],{"class":66,"line":194},[64,409,410],{"class":243},"            const",[64,412,413],{"class":247}," result",[64,415,335],{"class":74},[64,417,418],{"class":401}," await",[64,420,421],{"class":247}," dynamodb",[64,423,424],{"class":74},".",[64,426,427],{"class":254},"scan",[64,429,258],{"class":70},[64,431,432],{"class":247},"params",[64,434,354],{"class":70},[64,436,424],{"class":74},[64,438,439],{"class":254},"promise",[64,441,442],{"class":70},"()\n",[64,444,445,448],{"class":66,"line":202},[64,446,447],{"class":401},"            return",[64,449,297],{"class":74},[64,451,452,455,457,461],{"class":66,"line":210},[64,453,454],{"class":70},"                statusCode",[64,456,75],{"class":74},[64,458,460],{"class":459},"sx098"," 200",[64,462,315],{"class":74},[64,464,466,469,471,474,476,479,481,484,486,489,491],{"class":66,"line":465},17,[64,467,468],{"class":70},"                body",[64,470,75],{"class":74},[64,472,473],{"class":247}," JSON",[64,475,424],{"class":74},[64,477,478],{"class":254},"stringify",[64,480,258],{"class":70},[64,482,483],{"class":247},"result",[64,485,424],{"class":74},[64,487,488],{"class":247},"Items",[64,490,354],{"class":70},[64,492,315],{"class":74},[64,494,496],{"class":66,"line":495},18,[64,497,498],{"class":74},"            };\n",[64,500,502,505,508,510,513,515],{"class":66,"line":501},19,[64,503,504],{"class":74},"        }",[64,506,507],{"class":401},"catch",[64,509,341],{"class":70},[64,511,512],{"class":247},"e",[64,514,354],{"class":70},[64,516,405],{"class":74},[64,518,520,522],{"class":66,"line":519},20,[64,521,447],{"class":401},[64,523,297],{"class":74},[64,525,527,529,531,534],{"class":66,"line":526},21,[64,528,454],{"class":70},[64,530,75],{"class":74},[64,532,533],{"class":459}," 500",[64,535,315],{"class":74},[64,537,539,541,543,546,548,551],{"class":66,"line":538},22,[64,540,468],{"class":70},[64,542,75],{"class":74},[64,544,545],{"class":247}," e",[64,547,424],{"class":74},[64,549,550],{"class":247},"message",[64,552,315],{"class":74},[64,554,556],{"class":66,"line":555},23,[64,557,498],{"class":74},[64,559,561],{"class":66,"line":560},24,[64,562,563],{"class":74},"        }\n",[64,565,567],{"class":66,"line":566},25,[64,568,569],{"class":74},"}\n",[10,571,572],{},"そしてビルドしてテストをしても",[31,574,577],{"className":575,"code":576,"language":36},[34],"sam build\nsam local invoke -e events\u002Fevent.json\n\nInaccessible host: `127.0.0.1' at port `8000'. This service may not be available in the `ap-north-east1' region.\n",[38,578,576],{"__ignoreMap":40},[10,580,581],{},"とDynamoDBのホストに接続できていないというエラーが発生しました。色々検索した結果、以下の記事がキーとなり解決しました。",[10,583,584],{},[20,585,588],{"href":586,"rel":587},"https:\u002F\u002Ffuture-architect.github.io\u002Farticles\u002F20200323\u002F",[24],"Serverless連載1: SAMを使ったローカルテスト（Go編）",[48,590,591],{"id":591},"解決法",[10,593,594],{},"上記記事の図をみて一気に理解できました。原因はSAMのコンテナがDynamoDBのコンテナに接続できず、またホスト（localhost)の指定が間違っていたからです。",[596,597,599],"h3",{"id":598},"samもdockerで実行されている","SAMもdockerで実行されている",[10,601,602,603],{},"SAMは自動デプロイだけでなく、ローカルでのテストもサポートしています。",[20,604,607],{"href":605,"rel":606},"https:\u002F\u002Fdocs.aws.amazon.com\u002Fja_jp\u002Fserverless-application-model\u002Flatest\u002Fdeveloperguide\u002Fserverless-sam-cli-install-linux.html#serverless-sam-cli-install-linux-docker",[24],"テストではDockerを用いることがドキュメントにも書かれています。",[10,609,610,611,614,615,618,619,622],{},"LambdaのコードはDockerのあるコンテナにて実行されることになります。そのため、",[38,612,613],{},"localhost:8000","というのは私のホストOSの8000ポートでなく、SAMが実行されている環境の8000ポートに向いていたのです。SAMコンテナ内の",[38,616,617],{},"locahost:8000","にはDynamoDBなんてありませんから、",[38,620,621],{},"Inaccessible host"," になるのは当たり前です。",[10,624,625],{},"つまりやることはSAMコンテナネットワークと、DynamoDBコンテナネットワークを接続してあげる必要があります。",[596,627,629],{"id":628},"dynamodbの設定とテスト実行時の引数を与える","DynamoDBの設定とテスト実行時の引数を与える",[10,631,632],{},"先ほどのDynamoDBのdocker-compose.yamlを見てみると、ネットワークの設定があります。",[31,634,636],{"className":57,"code":635,"filename":59,"language":60,"meta":40,"style":40},"version: \"3\"\n\nservices:\n  dynamodb-local:\n    container_name: dynamodb-local\n    image: amazon\u002Fdynamodb-local\n    ports:\n      - 8000:8000\n    command: -jar DynamoDBLocal.jar -dbPath \u002Fdata -sharedDb\n    volumes:\n      - .\u002Fdata:\u002Fdata\n    networks:\n      - lambda-local\nnetworks:\n  lambda-local:\n    external: true #これ！\n",[38,637,638,650,654,660,666,674,682,688,694,702,708,714,720,726,732,738],{"__ignoreMap":40},[64,639,640,642,644,646,648],{"class":66,"line":67},[64,641,71],{"class":70},[64,643,75],{"class":74},[64,645,78],{"class":74},[64,647,82],{"class":81},[64,649,85],{"class":74},[64,651,652],{"class":66,"line":88},[64,653,92],{"emptyLinePlaceholder":91},[64,655,656,658],{"class":66,"line":95},[64,657,98],{"class":70},[64,659,101],{"class":74},[64,661,662,664],{"class":66,"line":104},[64,663,107],{"class":70},[64,665,101],{"class":74},[64,667,668,670,672],{"class":66,"line":112},[64,669,115],{"class":70},[64,671,75],{"class":74},[64,673,120],{"class":81},[64,675,676,678,680],{"class":66,"line":123},[64,677,126],{"class":70},[64,679,75],{"class":74},[64,681,131],{"class":81},[64,683,684,686],{"class":66,"line":134},[64,685,137],{"class":70},[64,687,101],{"class":74},[64,689,690,692],{"class":66,"line":142},[64,691,145],{"class":74},[64,693,148],{"class":81},[64,695,696,698,700],{"class":66,"line":151},[64,697,154],{"class":70},[64,699,75],{"class":74},[64,701,159],{"class":81},[64,703,704,706],{"class":66,"line":162},[64,705,165],{"class":70},[64,707,101],{"class":74},[64,709,710,712],{"class":66,"line":170},[64,711,145],{"class":74},[64,713,175],{"class":81},[64,715,716,718],{"class":66,"line":178},[64,717,181],{"class":70},[64,719,101],{"class":74},[64,721,722,724],{"class":66,"line":186},[64,723,145],{"class":74},[64,725,191],{"class":81},[64,727,728,730],{"class":66,"line":194},[64,729,197],{"class":70},[64,731,101],{"class":74},[64,733,734,736],{"class":66,"line":202},[64,735,205],{"class":70},[64,737,101],{"class":74},[64,739,740,742,744,747],{"class":66,"line":210},[64,741,213],{"class":70},[64,743,75],{"class":74},[64,745,746],{"class":218}," true",[64,748,750],{"class":749},"sC9rS"," #これ！\n",[10,752,753],{},"そしてSAMコンテナの立ち上げの際、このネットワークに接続できる引数があります。",[31,755,758],{"className":756,"code":757,"language":36},[34],"sam local invoke -e events\u002Fevent.json --docker-network lambda-local\n",[38,759,757],{"__ignoreMap":40},[10,761,762,765],{},[38,763,764],{},"--docker-network lambda-local"," を指定することで、DynamoDBコンテナのネットワークにアクセスできるようになります。そしてホストも以下のように書き換えます。",[31,767,769],{"className":233,"code":768,"filename":235,"language":236,"meta":40,"style":40},"var dynamoOpt = {\n    endpoint: \"http:\u002F\u002Fdynamodb-local:8000\",\n};\n",[38,770,771,781,796],{"__ignoreMap":40},[64,772,773,775,777,779],{"class":66,"line":67},[64,774,289],{"class":243},[64,776,292],{"class":247},[64,778,251],{"class":74},[64,780,297],{"class":74},[64,782,783,785,787,789,792,794],{"class":66,"line":88},[64,784,302],{"class":70},[64,786,75],{"class":74},[64,788,78],{"class":74},[64,790,791],{"class":81},"http:\u002F\u002Fdynamodb-local:8000",[64,793,312],{"class":74},[64,795,315],{"class":74},[64,797,798],{"class":66,"line":95},[64,799,320],{"class":74},[10,801,802],{},"実際のコードではホスト部分は環境変数に置き換えます。とりあえず上記ホストに変更して、もう一度先ほどのコマンドを実行しました。結果、なんとかDynamoDBに接続してCRUD操作ができるようになりました。",[10,804,805],{},"複数のコンテナを立てていたりすると、どこがどう繋がっているか分からなくなるので結構はまりました。汗）",[807,808,809],"style",{},"html pre.shiki code .s-wAU, html code.shiki .s-wAU{--shiki-default:#F07178}html pre.shiki code .sAklC, html code.shiki .sAklC{--shiki-default:#89DDFF}html pre.shiki code .sfyAc, html code.shiki .sfyAc{--shiki-default:#C3E88D}html pre.shiki code .sbqyR, html code.shiki .sbqyR{--shiki-default:#FF9CAC}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sJ14y, html code.shiki .sJ14y{--shiki-default:#C792EA}html pre.shiki code .s0W1g, html code.shiki .s0W1g{--shiki-default:#BABED8}html pre.shiki code .sdLwU, html code.shiki .sdLwU{--shiki-default:#82AAFF}html pre.shiki code .s7ZW3, html code.shiki .s7ZW3{--shiki-default:#BABED8;--shiki-default-font-style:italic}html pre.shiki code .s6cf3, html code.shiki .s6cf3{--shiki-default:#89DDFF;--shiki-default-font-style:italic}html pre.shiki code .sx098, html code.shiki .sx098{--shiki-default:#F78C6C}html pre.shiki code .sC9rS, html code.shiki .sC9rS{--shiki-default:#464B5D;--shiki-default-font-style:italic}",{"title":40,"searchDepth":95,"depth":95,"links":811},[812,813],{"id":50,"depth":88,"text":51},{"id":591,"depth":88,"text":591,"children":814},[815,816],{"id":598,"depth":95,"text":599},{"id":628,"depth":95,"text":629},[818],"ministack","2026-05-07","AWS SAMとDynamoDBの接続","md",null,{},"\u002Farticles\u002Faws-sam-disconnect-dymamodb-local",{"title":5,"description":820},"articles\u002Faws-sam-disconnect-dymamodb-local",[828,829,830],"aws","docker","serverless","util\u002Fsam_squirrel.png","wCqQZ02-pnfwd_-TA9YeBhfjRe0nMADGHPc1dk6e2z0",1780987139508]