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