使用 LocalStack 和 Docker 开发及测试 AWS 云应用程序

在现代应用开发中,将云应用程序部署到生产环境之前先在本地进行测试,有助于更快、更自信地发布。这种方法涉及在本地模拟服务,尽早识别和修复问题,并快速迭代,而无需承担成本或面对完整云环境的复杂性。像 LocalStack 这样的工具在此过程中变得非常宝贵,使您能够模拟 AWS 服务并容器化应用程序,以实现一致的、隔离的测试环境。

在本指南中,您将学习如何

  • 使用 Docker 启动 LocalStack 容器
  • 从非容器化应用程序连接到 LocalStack
  • 从容器化应用程序连接到 LocalStack

什么是 LocalStack?

LocalStack 是一个云服务模拟器,它可以在您的笔记本电脑上的单个容器中运行。它提供了一种功能强大、灵活且经济高效的方法,用于在本地测试和开发基于 AWS 的应用程序。

为什么使用 LocalStack?

在本地模拟 AWS 服务,您可以测试应用程序如何与 S3、Lambda 和 DynamoDB 等服务交互,而无需连接真实的 AWS 云。您可以快速迭代开发,避免在此阶段部署到云端的成本和复杂性。

通过在本地模拟这些服务的行为,LocalStack 可以实现更快的反馈循环。您的应用程序可以与外部 API 交互,但所有内容都在本地运行,无需处理云资源调配或网络延迟。

这使得验证集成和测试基于云的场景变得更容易,而无需在生产环境中配置 IAM 角色或策略。您可以在本地模拟复杂的云架构,只有在准备好时才将更改推送到 AWS。

将 LocalStack 与 Docker 结合使用

LocalStack 的 官方 Docker 镜像 提供了一种便捷的方式,可在您的开发机器上运行 LocalStack。它是免费使用的,运行无需任何 API 密钥。您甚至可以使用 LocalStack Docker Extension,通过图形用户界面使用 LocalStack。

先决条件

本操作指南需要以下先决条件

启动 LocalStack

使用以下步骤快速启动 LocalStack 演示

  1. 首先 克隆示例应用程序。打开终端并运行以下命令

    $ git clone https://github.com/dockersamples/todo-list-localstack-docker
    $ cd todo-list-localstack-docker
    
  2. 启动 LocalStack

    运行以下命令启动 LocalStack。

    $ docker compose -f compose-native.yml up -d
    

    此 Compose 文件还包含所需的 Mongo 数据库规范。您可以通过访问 Docker Desktop Dashboard 来验证服务是否已启动并正在运行。

    Diagram showing the LocalStack and Mongo container up and running on Docker Desktop
  3. 通过选择容器并检查日志来验证 LocalStack 是否已启动并正在运行。

    Diagram showing the logs of LocalStack container
  4. 创建本地 Amazon S3 存储桶

    当您使用 LocalStack 创建本地 S3 存储桶时,实际上是在模拟在 AWS 上创建 S3 存储桶。这使您无需实际的 AWS 账户即可测试和开发与 S3 交互的应用程序。

    要创建本地 Amazon S3 存储桶,您需要在系统上安装 awscli-local 软件包。此软件包提供 awslocal 命令,它是 AWS 命令行接口的一个精简包装器,用于 LocalStack。它让您可以在本地机器上的模拟环境中进行测试和开发,而无需访问真实的 AWS 服务。您可以在此处了解更多关于此实用工具的信息。

    $ pip install awscli-local
    

    使用以下命令在 LocalStack 环境中创建一个新的 S3 存储桶

    $ awslocal s3 mb s3://mysamplebucket
    

    命令 s3 mb s3://mysamplebucket 告诉 AWS CLI 创建一个名为 mysamplebucket 的新 S3 存储桶(mb 代表 make bucket,创建存储桶)。

    您可以通过在 Docker Desktop Dashboard 上选择 LocalStack 容器并查看日志来验证 S3 存储桶是否已创建。日志表明您的 LocalStack 环境已正确配置,您现在可以使用 mysamplebucket 来存储和检索对象。

    Diagram showing the logs of LocalStack that highlights the S3 bucket being created successfully

在开发中使用 LocalStack

现在您已经熟悉了 LocalStack,是时候看看它的实际应用了。在此演示中,您将使用一个包含 React 前端和 Node.js 后端的示例应用程序。此应用程序栈使用以下组件:

  • React:用户友好的前端,用于访问待办事项列表应用程序
  • Node:负责处理 HTTP 请求的后端。
  • MongoDB:一个用于存储所有待办事项列表数据的数据库
  • LocalStack:模拟 Amazon S3 服务并存储和检索图像。
Diagram showing the tech stack of the sample todo-list application that includes LocalStack, frontend and backend services

从非容器化应用连接到 LocalStack

现在是时候将您的应用程序连接到 LocalStack 了。index.js 文件位于 backend/ 目录中,是后端应用程序的主要入口点。

代码与 LocalStack 的 S3 服务交互,该服务通过 S3_ENDPOINT_URL 环境变量定义的端点进行访问,该端点通常在本地开发中设置为 http://localhost:4556

AWS SDK 中的 S3Client 配置为使用此 LocalStack 端点,以及同样来自环境变量的测试凭证(AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEY)。此设置允许应用程序在本地模拟的 S3 服务上执行操作,如同与真实的 AWS S3 交互一样,这使得代码在不同环境中具有灵活性。

代码使用 multermulter-s3 来处理文件上传。当用户通过 /upload 路由上传图像时,文件直接存储在 LocalStack 模拟的 S3 存储桶中。存储桶名称从环境变量 S3_BUCKET_NAME 中检索。每个上传的文件通过在原始文件名后附加当前时间戳来获得唯一名称。然后,该路由返回本地 S3 服务中上传文件的 URL,使其可以像托管在真实的 AWS S3 存储桶中一样访问。

让我们看看实际操作。首先启动 Node.js 后端服务。

  1. 切换到 backend/ 目录

    $ cd backend/
    
  2. 安装所需的依赖项

    $ npm install
    
  3. 设置 AWS 环境变量

    位于 backend/ 目录中的 .env 文件已经包含 LocalStack 用于模拟 AWS 服务的占位符凭证和配置值。AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEY 是占位符凭证,而 S3_BUCKET_NAMES3_ENDPOINT_URL 是配置设置。由于这些值已针对 LocalStack 正确设置,因此无需进行任何更改。

    提示

    考虑到您在 Docker 容器中运行 Mongo,并且后端 Node 应用程序在您的主机上原生运行,请确保在您的 .env 文件中设置了 MONGODB_URI=mongodb://localhost:27017/todos

    MONGODB_URI=mongodb://localhost:27017/todos
    AWS_ACCESS_KEY_ID=test
    AWS_SECRET_ACCESS_KEY=test
    S3_BUCKET_NAME=mysamplebucket
    S3_ENDPOINT_URL=http://localhost:4566
    AWS_REGION=us-east-1

    尽管 AWS SDK 通常可能使用以 AWS_ 开头的环境变量,但此特定应用程序直接引用 index.js 文件(位于 backend/ 目录下)中的以下 S3_* 变量来配置 S3Client

    const s3 = new S3Client({
      endpoint: process.env.S3_ENDPOINT_URL, // Use the provided endpoint or fallback to defaults
      credentials: {
        accessKeyId: process.env.AWS_ACCESS_KEY_ID || 'default_access_key', // Default values for development
        secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY || 'default_secret_key',  
      },
    });
  4. 启动后端服务器

    $ node index.js
    

    您将看到后端服务已在端口 5000 成功启动的消息。

启动前端服务

要启动前端服务,请打开新的终端并按照以下步骤操作

  1. 导航到 frontend 目录

    $ cd frontend
    
  2. 安装所需的依赖项

    $ npm install
    
  3. 启动前端服务

    $ npm run dev
    

    现在,您应该看到以下消息

    VITE v5.4.2  ready in 110 ms
    ➜  Local: http://localhost:5173/
    ➜  Network: use --host to expose
    ➜  press h + enter to show help
    

    您现在可以通过 http://localhost:5173 访问该应用程序。请选择一个图像文件并点击“Upload”(上传)按钮来上传图像。

    Diagram showing a working todo-list application

    您可以通过检查 LocalStack 容器日志来验证图像是否已上传到 S3 存储桶

    Diagram showing the logs of the LocalStack that highlights image uploaded to the emulated S3 bucket

    状态码 200 表示 putObject 操作(涉及将对象上传到 S3 存储桶)在 LocalStack 环境中成功执行。LocalStack 记录此条目,以便了解正在执行的操作。这有助于调试和确认您的应用程序是否正在正确地与模拟的 AWS 服务交互。

    由于 LocalStack 旨在在本地模拟 AWS 服务,此日志条目表明您的应用程序在本地沙箱环境中执行云操作时按预期工作。

从容器化 Node 应用连接到 LocalStack

既然您已经学会了如何将非容器化的 Node.js 应用程序连接到 LocalStack,现在是时候探索在容器化环境中运行完整应用程序栈所需的更改了。为此,您将创建一个 Compose 文件,指定所有必需的服务 - 前端、后端、数据库和 LocalStack。

  1. 检查 Docker Compose 文件。

    以下 Docker Compose 文件定义了四个服务:backendfrontendmongodblocalstackbackendfrontend 服务是您的 Node.js 应用程序,而 mongodb 提供数据库,localstack 模拟像 S3 这样的 AWS 服务。

    backend 服务依赖于 localstackmongodb 服务,确保它们在启动前运行。它还使用 .env 文件来设置环境变量。frontend 服务依赖于 backend 并设置 API URL。mongodb 服务使用持久卷进行数据存储,而 localstack 配置为运行 S3 服务。此设置使您能够在本地使用类似 AWS 的服务开发和测试应用程序。

    services:
      backend:
        build:
          context: ./backend
          dockerfile: Dockerfile
        ports:
          - 5000:5000
        depends_on:
          - localstack
          - mongodb
        env_file:
          - backend/.env
    
      frontend:
        build:
          context: ./frontend
          dockerfile: Dockerfile
        ports:
          - 5173:5173
        depends_on:
          - backend
        environment:
          - REACT_APP_API_URL=http://backend:5000/api
    
      mongodb:
        image: mongo
        container_name: mongodb
        volumes:
          - mongodbdata:/data/db
        ports:
          - 27017:27017
    
      localstack:
        image: localstack/localstack
        container_name: localstack
        ports:
          - 4566:4566
        environment:
          - SERVICES=s3
          - GATEWAY_LISTEN=0.0.0.0:4566
        volumes:
          - ./localstack:/docker-entrypoint-initaws.d"
    
    volumes:
      mongodbdata:
  2. 修改 backend/ 目录下的 .env 文件,使资源使用内部网络名称进行连接。

    提示

    根据之前的 Compose 文件,应用程序将使用主机名 localstack 连接到 LocalStack,而 Mongo 将使用主机名 mongodb 连接。

    MONGODB_URI=mongodb://mongodb:27017/todos
    AWS_ACCESS_KEY_ID=test
    AWS_SECRET_ACCESS_KEY=test
    S3_BUCKET_NAME=mysamplebucket
    S3_ENDPOINT_URL=http://localstack:4566
    AWS_REGION=us-east-1
  3. 停止正在运行的服务

    通过在终端中按“Ctrl+C”确保停止上一步中的 Node 前端和后端服务。此外,您需要通过在 Docker Desktop Dashboard 中选择 LocalStack 和 Mongo 容器并点击“Delete”(删除)按钮来停止它们。

  4. 在您克隆的项目目录的根目录下执行以下命令来启动应用程序栈

    $ docker compose -f compose.yml up -d --build
    

    稍等片刻,应用程序将启动并运行。

  5. 手动创建一个 S3 存储桶

    AWS S3 存储桶不会由 Compose 文件预先创建。运行以下命令在 LocalStack 环境中创建一个新的存储桶

    $ awslocal s3 mb s3://mysamplebucket
    

    该命令创建一个名为 mysamplebucket 的 S3 存储桶。

    打开 http://localhost:5173 访问完整的待办事项列表应用程序,并开始向 Amazon S3 存储桶上传图像。

    提示

    为了优化性能并减少开发过程中的上传时间,请考虑上传较小的图像文件。较大的图像可能需要更长时间处理,并可能影响应用程序的整体响应速度。

总结

本指南已向您介绍了如何使用 LocalStack 和 Docker 设置本地开发环境。您已学会如何在本地测试基于 AWS 的应用程序,从而降低成本并提高开发工作流程的效率。

页面选项