When using local DynamoDB with a docker-network the SDK cannot find the resource

  amazon-dynamodb, aws-sam, docker

I am using AWS SAM to build my application and need to be able to test it locally. I was successful when recreating this blog post How to Deploy a Local Serverless Application With AWS SAM. When following the same steps on a different project, I run into errors. I created a docker network,

docker network create project-name

a local dynamodb instance,

docker run --network project-name --name dynamodb -d -p 8000:8000 amazon/dynamodb-local

and a table

aws dynamodb create-table --table-name Cache-local --attribute-definitions AttributeName=ItemId,AttributeType=S --key-schema AttributeName=ItemId,KeyType=HASH --provisioned-throughput ReadCapacityUnits=5,WriteCapacityUnits=5 --endpoint-url http://localhost:8000.

I then build and locally invoke the lambda function DBSan.

sam build use-container

APP_ENV=local sam local invoke DBScan --docker-network project-name --profile poto

and get the error, {"errorMessage": "An error occurred (ResourceNotFoundException) when calling the DescribeTable operation: Cannot do operations on a non-existent table", "errorType": "ResourceNotFoundException", "stackTrace": [" File "/var/task/app.py", line 27, in dbScann print(table.creation_date_time)n", " File "/var/runtime/boto3/resources/factory.py", line 339, in property_loadern self.load()n", " File "/var/runtime/boto3/resources/factory.py", line 505, in do_actionn response = action(self, *args, **kwargs)n", " File "/var/runtime/boto3/resources/action.py", line 83, in __call__n response = getattr(parent.meta.client, operation_name)(*args, **params)n", " File "/var/runtime/botocore/client.py", line 357, in _api_calln return self._make_api_call(operation_name, kwargs)n", " File "/var/runtime/botocore/client.py", line 676, in _make_api_calln raise error_class(parsed_response, operation_name)n"]}

here is how I am setting up the connection:

template.yaml

  DBScan:
    Type: AWS::Serverless::Function 
    Properties:
      CodeUri: src/
      Handler: app.dbScan
      Runtime: python3.8
      MemorySize: 512
      Timeout: 600
      Layers: 
        - !Ref DependenciesLayer
      Environment:
        Variables:
          APP_ENV: !Ref AppEnv
          REGION_NAME: us-east-2
      Events:
        DBScan:
          Type: Api 
          Properties:
            Path: /dbScan
            Method: GET
      Policies:
        - AWSLambdaBasicExecutionRole
        - DynamoDBCrudPolicy:
            TableName: !Ref CacheTable

app.py

app_env = os.environ['APP_ENV']
if app_env == 'local':
    print('in local environment')
    dynamo = boto3.resource('dynamodb', endpoint_url='http://dynamodb:8000/')
else:
    dynamo = boto3.resource('dynamodb', region_name=region_name)
def dbScan(event, context):
    print("Recieved event: " + json.dumps(event, indent=2))
    table_name = 'Cache-local'
    table = dynamo.Table(table_name)
    print(table.creation_date_time)
    return respond(None, res='test')

I am able to see and interact with dynamo through dynamodb-admin, I manually entered in some test data. Also when I run

aws dynamodb scan --table-name Cache-local --endpoint-url http://localhost:8000
I can successfully scan dynamodb. When I changed the endpoint_url='http://localhost:8000', I get a different error

{"errorMessage": "Could not connect to the endpoint URL: "http://localhost:8000/"", "errorType": "EndpointConnectionError", "stackTrace": [" File "/var/task/app.py", line 27, in dbScann print(table.creation_date_time)n", " File "/var/runtime/boto3/resources/factory.py", line 339, in property_loadern self.load()n", " File "/var/runtime/boto3/resources/factory.py", line 505, in do_actionn response = action(self, *args, **kwargs)n", " File "/var/runtime/boto3/resources/action.py", line 83, in __call__n response = getattr(parent.meta.client, operation_name)(*args, **params)n", " File "/var/runtime/botocore/client.py", line 357, in _api_calln return self._make_api_call(operation_name, kwargs)n", " File "/var/runtime/botocore/client.py", line 662, in _make_api_calln http, parsed_response = self._make_request(n", " File "/var/runtime/botocore/client.py", line 682, in _make_requestn return self._endpoint.make_request(operation_model, request_dict)n", " File "/var/runtime/botocore/endpoint.py", line 102, in make_requestn return self._send_request(request_dict, operation_model)n", " File "/var/runtime/botocore/endpoint.py", line 136, in _send_requestn while self._needs_retry(attempts, operation_model, request_dict,n", " File "/var/runtime/botocore/endpoint.py", line 253, in _needs_retryn responses = self._event_emitter.emit(n", " File "/var/runtime/botocore/hooks.py", line 356, in emitn return self._emitter.emit(aliased_event_name, **kwargs)n", " File "/var/runtime/botocore/hooks.py", line 228, in emitn return self._emit(event_name, kwargs)n", " File "/var/runtime/botocore/hooks.py", line 211, in _emitn response = handler(**kwargs)n", " File "/var/runtime/botocore/retryhandler.py", line 183, in __call__n if self._checker(attempts, response, caught_exception):n", " File "/var/runtime/botocore/retryhandler.py", line 250, in __call__n should_retry = self._should_retry(attempt_number, response,n", " File "/var/runtime/botocore/retryhandler.py", line 277, in _should_retryn return self._checker(attempt_number, response, caught_exception)n", " File "/var/runtime/botocore/retryhandler.py", line 316, in __call__n checker_response = checker(attempt_number, response,n", " File "/var/runtime/botocore/retryhandler.py", line 222, in __call__n return self._check_caught_exception(n", " File "/var/runtime/botocore/retryhandler.py", line 359, in _check_caught_exceptionn raise caught_exceptionn", " File "/var/runtime/botocore/endpoint.py", line 200, in _do_get_responsen http_response = self._send(request)n", " File "/var/runtime/botocore/endpoint.py", line 269, in _sendn return self.http_session.send(request)n", " File "/var/runtime/botocore/httpsession.py", line 343, in sendn raise EndpointConnectionError(endpoint_url=request.url, error=e)n"]}

Also, when I create a standalone script I can successfully connect to dynamodb.

import boto3

dynamodb = boto3.resource('dynamodb', endpoint_url='http://localhost:8000')
table = dynamodb.Table('Cache-local')
print(table.creation_date_time)

>>> 2021-06-17 09:23:44.157000-06:00

Source: Docker Questions

LEAVE A COMMENT