每天进步一点:配置localstack本地测试AWS功能

今天开始试用localstack,感觉非常好用。用localstack开发AWS应用非常方便,下面把整个过程记录一下。整个过程是基于这个英文教程的,但下面只是我自己的理解和笔记,并不是对英文教程的翻译。

localstack

LocalStack是什么?

Localstack允许你在本地尝试一系列的AWS服务,而无需担心费用问题。

  • 支持离线方式
  • 你无需和他人共享AWS资源,这样想怎么搞就怎么搞,不用担心影响到别人
  • 轻松管理本地资源
  • 完全免费
  • 尝试AWS服务而不需要AWS账号

设置

首先确保安装了Docker, AWS CLI, 然后确保运行了aws configure来生成并保存相关密码。

接下来创建一个项目,比如“test1", 并在该项目中创建一些文件:

mkdir test1
cd test1
touch index.js docker-compose.yml .env
mkdir .localstack

复制一个图片,比如:test.jpg 到项目目录下。

进行npm配置和安装配套AWS 包:

npm init 
npm install aws-sdk dotenv

编辑 docker-compose.yml 并添加如下内容:

version: '3.2'
services:
  localstack:
    image: localstack/localstack:latest
    container_name: localstack_demo
    ports:
      - '4563-4599:4563-4599'
      - '8055:8080'
    environment:
      - SERVICES=s3
      - DEBUG=1
      - DATA_DIR=/tmp/localstack/data
    volumes:
      - './.localstack:/tmp/localstack'
      - '/var/run/docker.sock:/var/run/docker.sock'

启动docker容器:

docker-compose up 

等个2分钟左右你就可以在浏览器中访问 localstack 界面了: http://localhost:8055/

对于本地的AWS S3,可以通过如下端口访问: http://localhost:4572/

现在你就可以在本地测试AWS的服务了!

通过localstack来测试AWS S3服务

通过localstack来创建一个S3 bucket:

aws --endpoint-url=http://localhost:4572 s3 mb s3://demo-bucket

注意:这里的 --endpoint-url 参数指定了 localstack 中对应的 s3 访问路径。

在 localstack 的日志中,你会看到如下信息:

localstack_demo | 2019-12-06 15:10:14,909:API: 127.0.0.1 - - [06/Dec/2019 15:10:14] "PUT /demo-bucket HTTP/1.1" 200 

在 localstack S3 的Web界面中,你可以看到:

<Buckets>
<Bucket>
<Name>demo-bucket</Name>
<CreationDate>2006-02-03T16:45:09.000Z</CreationDate>
</Bucket>
</Buckets>

为S3 bucket添加访问控制列表ACL:

aws --endpoint-url=http://localhost:4572 s3api put-bucket-acl --bucket demo-bucket --acl public-read

现在,你的S3 bucket就对外公开了。

现在你可以检查一下这个文件: .localstack/data/s3_api_calls.json

{"a": "s3", "m": "PUT", "p": "/demo-bucket", "d": "XXXXXXXX", "h": {"host": "localhost", "Accept-Encoding": "identity", "User-Agent": "aws-cli/1.16.183 Python/3.6.9 Linux/4.15.
0-72-generic botocore/1.12.253", "X-Amz-Date": "20191206T151014Z", "X-Amz-Content-SHA256": "xxxx", "Authorization": "AWS4-HMAC-SHA256 Credential=XXXXXX, SignedHeaders=host;x-amz-content-sha256;x-amz-date, Signature=xxxx", "Content-Length": "153", "X-Forwarded-For": "172.30.0.1, 0.0.0.0:4572", "content-type": "binary/octet-str
eam"}}
{"a": "s3", "m": "PUT", "p": "/demo-bucket?acl", "d": "", "h": {"host": "localhost", "Accept-Encoding": "identity", "x-amz-a
cl": "public-read", "User-Agent": "aws-cli/1.16.183 Python/3.6.9 Linux/4.15.0-72-generic botocore/1.12.253", "X-Amz-Date": "
20191206T151327Z", "X-Amz-Content-SHA256": "xxxx", "Authorizatio
n": "AWS4-HMAC-SHA256 Credential=xxxx", "Content-Length": "
0", "X-Forwarded-For": "172.30.0.1, 0.0.0.0:4572", "content-type": "binary/octet-stream"}}

可以看到,你的所有操作都被记录了下来。

编辑 .env 文件,并添加如下内容:

AWS_ACCESS_KEY_ID='123'
AWS_SECRET_KEY='xyz'
AWS_BUCKET_NAME='demo-bucket'

其实这里 AWS key & secret 填什么都可以,只要不是空字符串就行。localstack 并不进行身份验证.

创建文件: aws.js

const AWS = require('aws-sdk')
require('dotenv').config()

const credentials = {
   accessKeyId: process.env.AWS_ACCESS_KEY_ID,
   secretAccessKey: process.env.AWS_SECRET_KEY,
}

const useLocal = process.env.NODE_ENV !== 'production'

const bucketName = process.env.AWS_BUCKET_NAME

const s3client = new AWS.S3({
   credentials,

   endpoint: useLocal ? 'http://localhost:4572' : undefined,
   s3ForcePathStyle: true,
})

const uploadFile = async (data, fileName) =>
   new Promise((resolve) => {
      s3client.upload(
         {
            Bucket: bucketName,
            Key: fileName,
            Body: data,
         },
         (err, response) => {
            if (err) throw err
            resolve(response)
         },
      )
   })

module.exports = uploadFile

创建文件 test-upload.js:

const fs = require('fs')
const path = require('path')
const uploadFile = require('./aws')

const testUpload = () => {
    const filePath = path.resolve(__dirname, 'test.jpg')
    const fileStream = fs.createReadStream(filePath)
    const now = new Date()
    const fileName = `test-image-${now.toISOString()}.jpg`
    uploadFile(fileStream, fileName).then((response) => {
        console.log(":)")
        console.log(response)
    }).catch((err) => {
        console.log(":|")
        console.log(err)
    })
}

testUpload()

运行如下命令进行测试:

node test-upload.js

从docker日志中你可以看到对应的图片路径,例如:

http://localhost:4572/demo-bucket/test-image-2019-12-06T15%3A28%3A57.037Z.jpg

如果再次检查文件: .localstack/data/s3_api_calls.json, 你会看到图片被转换为二进制数据并被存储。