使用 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 擴充套件透過圖形使用者介面使用 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 儲存桶。這使您能夠測試和開發與 S3 互動的應用程式,而無需實際的 AWS 賬戶。

    要建立本地 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 了。位於 `backend/` 目錄中的 `index.js` 檔案是後端應用程式的主要入口點。

此程式碼與 LocalStack 的 S3 服務互動,該服務透過 `S3_ENDPOINT_URL` 環境變數定義,通常在本地開發中設定為 `https://:4556`。

AWS SDK 中的 `S3Client` 配置為使用此 LocalStack 端點,以及同樣從環境變數獲取的測試憑據(`AWS_ACCESS_KEY_ID` 和 `AWS_SECRET_ACCESS_KEY`)。此設定允許應用程式在本地模擬的 S3 服務上執行操作,就像它在與真實的 AWS S3 互動一樣,從而使程式碼適用於不同的環境。

此程式碼使用 `multer` 和 `multer-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_ID` 和 `AWS_SECRET_ACCESS_KEY` 是佔位符憑據,而 `S3_BUCKET_NAME` 和 `S3_ENDPOINT_URL` 是配置設定。無需更改,因為這些值已為 LocalStack 正確設定。

    提示

    鑑於您在 Docker 容器中執行 Mongo,並且後端 Node 應用程式在您的主機上本機執行,請確保您的 `.env` 檔案中設定了 `MONGODB_URI=mongodb://:27017/todos`。

    MONGODB_URI=mongodb://:27017/todos
    AWS_ACCESS_KEY_ID=test
    AWS_SECRET_ACCESS_KEY=test
    S3_BUCKET_NAME=mysamplebucket
    S3_ENDPOINT_URL=https://: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: https://:5173/
    ➜  Network: use --host to expose
    ➜  press h + enter to show help
    

    您現在可以透過 https://:5173 訪問該應用程式。繼續,透過選擇影像檔案並點選“上傳”按鈕來上傳影像。

    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 檔案定義了四個服務:`backend`、`frontend`、`mongodb` 和 `localstack`。`backend` 和 `frontend` 服務是您的 Node.js 應用程式,而 `mongodb` 提供資料庫,`localstack` 模擬 S3 等 AWS 服務。

    `backend` 服務依賴於 `localstack` 和 `mongodb` 服務,確保它們在啟動前執行。它還使用 `.env` 檔案來獲取環境變數。`frontend` 服務依賴於後端並設定 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 容器並選擇“刪除”按鈕來停止它們。

  4. 在克隆專案目錄的根目錄執行以下命令,啟動應用程式堆疊

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

    稍等片刻,應用程式就會啟動並執行。

  5. 手動建立 S3 儲存桶

    AWS S3 儲存桶未由 Compose 檔案預先建立。執行以下命令在 LocalStack 環境中建立新的儲存桶

    $ awslocal s3 mb s3://mysamplebucket
    

    該命令建立一個名為 `mysamplebucket` 的 S3 儲存桶。

    開啟 https://:5173 訪問完整的待辦事項列表應用程式,並開始向 Amazon S3 儲存桶上傳影像。

    提示

    為了最佳化開發期間的效能並縮短上傳時間,請考慮上傳較小的影像檔案。較大的影像可能需要更長的處理時間,並可能影響應用程式的整體響應能力。

回顧

本指南已引導您使用 LocalStack 和 Docker 設定本地開發環境。您已瞭解如何在本地測試基於 AWS 的應用程式,從而降低成本並提高開發工作流程的效率。