Amazon web services 将AWS SAM本地与docker中的dynamodb连接

Amazon web services 将AWS SAM本地与docker中的dynamodb连接,amazon-web-services,docker,amazon-dynamodb,aws-sam-cli,Amazon Web Services,Docker,Amazon Dynamodb,Aws Sam Cli,我已经使用aws sam local设置了一个api网关/aws lambda对,并确认运行后可以成功调用它 sam本地启动api 然后,我在docker容器中添加了一个本地dynamodb实例,并使用aws cli在其上创建了一个表 但是,在向lambda添加代码以写入我收到的dynamodb实例之后: 2018-02-22T11:13:16.172Z ed9ab38e-fb54-18a4-0852-db7e5b56c8cd错误: 无法写入表:{“消息”:“连接” 0.0.0.0:8000,“

我已经使用aws sam local设置了一个api网关/aws lambda对,并确认运行后可以成功调用它

sam本地启动api

然后,我在docker容器中添加了一个本地dynamodb实例,并使用aws cli在其上创建了一个表

但是,在向lambda添加代码以写入我收到的dynamodb实例之后:

2018-02-22T11:13:16.172Z ed9ab38e-fb54-18a4-0852-db7e5b56c8cd错误: 无法写入表:{“消息”:“连接” 0.0.0.0:8000,“代码”:“NetworkingError”,“errno”:“ECONNREFUSED”,“syscall”:“connect”,“address”:“0.0.0.0”,“port”:8000,“region”:“eu-west-2”,“主机名”:“0.0.0.0”,“retryable”:true,“time”:“2018-02-22T11:13:16.165Z”} 从命令写入事件: {“名称”:“测试”,“地理位置”:“xyz”,“类型”:“createDestination”}结束 请求ID:ed9ab38e-fb54-18a4-0852-db7e5b56c8cd

我在网上看到,您可能需要连接到同一个docker网络,因此我创建了一个网络
docker网络create lambda local
,并将我的start命令更改为:

sam本地启动api——docker网络lambda本地

docker run-v“$PWD”:/dynamodb_local_db-p 8000:8000——网络=lambda local cnadiminti/dynamodb local:latest

但仍然收到相同的错误

sam local正在打印连接容器98B19370AB92F3378CE380E9C840177905A49FC986597FEF9EF589E624BEAC3到网络lambda local的
2018/02/22 11:12:51

我正在使用以下方法创建DynamodB客户端:

const AWS = require('aws-sdk')
const dynamodbURL = process.env.dynamodbURL || 'http://0.0.0.0:8000'
const awsAccessKeyId = process.env.AWS_ACCESS_KEY_ID || '1234567'
const awsAccessKey = process.env.AWS_SECRET_ACCESS_KEY || '7654321'
const awsRegion = process.env.AWS_REGION || 'eu-west-2'

console.log(awsRegion, 'initialising dynamodb in region: ')

let dynamoDbClient
const makeClient = () => {
  dynamoDbClient = new AWS.DynamoDB.DocumentClient({
    endpoint: dynamodbURL,
    accessKeyId: awsAccessKeyId,
    secretAccessKey: awsAccessKey,
    region: awsRegion
  })
  return dynamoDbClient
}

module.exports = {
  connect: () => dynamoDbClient || makeClient()
}
检查我的代码正在创建的dynamodbclient

DocumentClient {
  options:
   { endpoint: 'http://0.0.0.0:8000',
     accessKeyId: 'my-key',
     secretAccessKey: 'my-secret',
     region: 'eu-west-2',
     attrValue: 'S8' },
  service:
   Service {
     config:
      Config {
        credentials: [Object],
        credentialProvider: [Object],
        region: 'eu-west-2',
        logger: null,
        apiVersions: {},
        apiVersion: null,
        endpoint: 'http://0.0.0.0:8000',
        httpOptions: [Object],
        maxRetries: undefined,
        maxRedirects: 10,
        paramValidation: true,
        sslEnabled: true,
        s3ForcePathStyle: false,
        s3BucketEndpoint: false,
        s3DisableBodySigning: true,
        computeChecksums: true,
        convertResponseTypes: true,
        correctClockSkew: false,
        customUserAgent: null,
        dynamoDbCrc32: true,
        systemClockOffset: 0,
        signatureVersion: null,
        signatureCache: true,
        retryDelayOptions: {},
        useAccelerateEndpoint: false,
        accessKeyId: 'my-key',
        secretAccessKey: 'my-secret' },
     endpoint:
      Endpoint {
        protocol: 'http:',
        host: '0.0.0.0:8000',
        port: 8000,
        hostname: '0.0.0.0',
        pathname: '/',
        path: '/',
        href: 'http://0.0.0.0:8000/' },
     _clientId: 1 },
  attrValue: 'S8' }
这个设置应该工作吗?我如何让他们互相交谈

----编辑----

根据twitter对话,值得一提的是(也许)我可以在CLI和webshell中与dynamodb交互

非常感谢以回购为例的

这让我找到了答案

  • dynamodb的docker容器在我的 机器(这就是我可以与之交互的原因)

  • SAM local的docker容器在我的 机器

  • 但它们并不是在127.0.0.1上相互关联的

因此:

指示我将连接代码更改为:

const AWS = require('aws-sdk')
const awsRegion = process.env.AWS_REGION || 'eu-west-2'

let dynamoDbClient
const makeClient = () => {
  const options = {
    region: awsRegion
  }
  if(process.env.AWS_SAM_LOCAL) {
    options.endpoint = 'http://dynamodb:8000'
  }
  dynamoDbClient = new AWS.DynamoDB.DocumentClient(options)
  return dynamoDbClient
}

module.exports = {
  connect: () => dynamoDbClient || makeClient()
}
重点是:

if(process.env.AWS_SAM_LOCAL) {
  options.endpoint = 'http://dynamodb:8000'
}
从SAM本地docker容器的上下文中,dynamodb容器通过其名称公开

我的两个启动命令最终为:

docker run-d-v“$PWD”:/dynamodb_local_db-p 8000:8000——网络lambda local——名称dynamodb cnadiminti/dynamodb local

AWS_REGION=eu-west-2 sam本地启动api——docker网络lambda本地


这里唯一的改变是给dynamodb容器一个名称

,如果您在mac上使用sam local,就像许多开发人员一样,您应该能够使用它

options.endpoint=”http://docker.for.mac.localhost:8000“

或者在docker的较新安装上

options.endpoint=”http://host.docker.internal:8000“


不必像Paul那样执行上面显示的多个命令(但这可能更不依赖于平台?)。

正如@Paul所提到的,它是关于在docker容器(lambda和数据库)之间配置您的网络

另一种对我有效的方法(使用docker compose)

docker compose:

version: '2.1'

services:
  db:
    image: ...
    ports:
      - "3306:3306"
    networks:
      - my_network
    environment:
      ...
    volumes:
      ...

networks:
  my_network:
然后,在
docker compose up
之后,运行
docker network ls
将显示:

NETWORK ID          NAME                        DRIVER              SCOPE
7eb440d5c0e6        dev_my_network              bridge              local
我的docker容器名是
dev\u db\u 1

我的js代码是:

const connection = mysql.createConnection({
    host: "dev_db_1",
    port: 3306,
    ...
});
然后,运行
sam
命令:

sam local invoke --docker-network dev_my_network -e my.json
堆栈:

  • 码头工人:18.03.1-ce
  • Docker compose:1.21.1
  • MacOS HighSierra 10.13.6
如果您使用运行DynamoDB,我认为使用SAM的LocalStack网络的正确命令是:

sam本地启动api--env vars env.json--docker network localstack\u默认值
在代码中,LocalStack主机名应该是
LocalStack\u LocalStack\u 1

const dynamoDbDocumentClient=new AWS.DynamoDB.DocumentClient({
端点:process.env.AWS_SAM_LOCAL?
'http://localstack_localstack_1:4569' :
未定义,
});

但是,我使用docker compose up启动了LocalStack。使用
pip
CLI工具启动LocalStack可能会导致不同的标识符。

SAM
在引擎盖下启动docker容器
lambci/lambda
,如果您有另一个容器承载
dynamodb
,例如,或您想要连接lambda的任何其他服务,因此,您应该在同一网络中拥有这两个

假设dynamodb(注意
--name
,现在这是端点)

这将导致类似的结果

0e35b1c90cf0....
要知道这是在哪个网络中创建的,请执行以下操作:

docker inspect 0e35b1c90cf0
它应该会给你一些

...
Networks: {
     "services_default": {//this is the <<myNetworkName>>

....
重要提示:您的lambda代码现在应该具有指向dynamo的端点,指向
DynamoDBEndpoint

比如说:

if(process.env.AWS_SAM_LOCAL) {
  options.endpoint = 'http://DynamoDBEndpoint:8000'
}
测试一切:

使用
lambci:lambda

这应该只列出其他dynamodb容器中的所有表

docker run -ti --rm --network myNetworkName lambci/lambda:build-go1.x \
   aws configure set aws_access_key_id "xxx" && \
   aws configure set aws_secret_access_key "yyy" &&  \
   aws --endpoint-url=http://DynamoDBEndpoint:4569 --region=us-east-1 dynamodb list-tables
或者调用函数:(例如,与NodeJS相同)

有关lambci/lambda的更多信息,请参见

使用
SAM
(它使用相同的容器
lmabci/lambda
):

sam local invoke --event myEventData.json --docker-network myNetworkName MyFuncName
如果您想查看更多详细信息,可以始终使用
--debug
选项

或者,您也可以使用
http://host.docker.internal:8000
没有玩docker的麻烦,此URL在内部保留,允许您访问主机,但请确保在启动dynamodb容器时公开端口8000。虽然它很简单,但并不是在所有的操作系统中都能工作。欲了解更多详情,请访问ab
docker run -ti --rm --network myNetworkName lambci/lambda:build-go1.x \
   aws configure set aws_access_key_id "xxx" && \
   aws configure set aws_secret_access_key "yyy" &&  \
   aws --endpoint-url=http://DynamoDBEndpoint:4569 --region=us-east-1 dynamodb list-tables
#Golang
docker run --rm -v "$PWD":/var/task lambci/lambda:go1.x handlerName '{"some": "event"}'
#Same for NodeJS 
docker run --rm -v "$PWD":/var/task lambci/lambda:nodejs10.x index.handler
sam local invoke --event myEventData.json --docker-network myNetworkName MyFuncName
version: '3.5'

services:
  dynamo:
    container_name: abp-sam-nestjs-dynamodb
    image: amazon/dynamodb-local
    networks:
      - backend
    ports:
      - '8000:8000'
    volumes:
      - dynamodata:/home/dynamodblocal
    working_dir: /home/dynamodblocal
    command: '-jar DynamoDBLocal.jar -sharedDb -dbPath .'

networks:
  backend:
    name: abp-sam-backend

volumes:
  dynamodata: {}

sam local start-api -t sam-template.yml --docker-network abp-sam-backend --skip-pull-image --profile default --parameter-overrides 'ParameterKey=StageName,ParameterValue=local ParameterKey=DDBTableName,ParameterValue=local-SingleTable'