LocalStack AWS 本地模擬器

使用 LocalStack 在本地模擬 AWS 服務,加速開發測試流程,減少雲端開支

專案簡介

LocalStack 是一個完整的 AWS 雲端模擬器,可在本地執行。支援 S3、Lambda、DynamoDB、SQS 等數十種 AWS 服務,讓開發者能在不連接真實 AWS 的情況下開發和測試。

GitHub Stars: 64K+

主要功能

  • 本地 AWS - 模擬 80+ AWS 服務
  • 快速迭代 - 無需等待雲端部署
  • 節省成本 - 減少開發環境費用
  • 離線開發 - 不需網路連線
  • CI/CD 整合 - 自動化測試

快速開始

Docker Compose

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
version: '3.8'
services:
  localstack:
    image: localstack/localstack
    ports:
      - "4566:4566"
      - "4510-4559:4510-4559"
    environment:
      - SERVICES=s3,lambda,dynamodb,sqs,sns
      - DEBUG=1
      - DOCKER_HOST=unix:///var/run/docker.sock
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock"
      - "./localstack:/var/lib/localstack"
1
docker compose up -d

Docker Run

1
2
3
4
docker run --rm -it \
  -p 4566:4566 \
  -p 4510-4559:4510-4559 \
  localstack/localstack

AWS CLI 設定

設定 Profile

1
2
3
4
5
aws configure --profile localstack
# AWS Access Key ID: test
# AWS Secret Access Key: test
# Default region name: us-east-1
# Default output format: json

使用 Endpoint

1
aws --endpoint-url=http://localhost:4566 s3 ls

別名設定

1
2
# ~/.bashrc 或 ~/.zshrc
alias awslocal='aws --endpoint-url=http://localhost:4566'

常用服務

S3

1
2
3
4
5
6
7
8
# 建立 Bucket
awslocal s3 mb s3://my-bucket

# 上傳檔案
awslocal s3 cp file.txt s3://my-bucket/

# 列出檔案
awslocal s3 ls s3://my-bucket/

Lambda

1
2
3
4
5
6
# lambda_function.py
def handler(event, context):
    return {
        'statusCode': 200,
        'body': 'Hello from LocalStack!'
    }
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# 打包
zip function.zip lambda_function.py

# 建立函數
awslocal lambda create-function \
    --function-name my-function \
    --runtime python3.9 \
    --handler lambda_function.handler \
    --zip-file fileb://function.zip \
    --role arn:aws:iam::000000000000:role/lambda-role

# 呼叫
awslocal lambda invoke \
    --function-name my-function \
    response.json

DynamoDB

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# 建立表格
awslocal dynamodb create-table \
    --table-name Users \
    --attribute-definitions AttributeName=id,AttributeType=S \
    --key-schema AttributeName=id,KeyType=HASH \
    --billing-mode PAY_PER_REQUEST

# 新增項目
awslocal dynamodb put-item \
    --table-name Users \
    --item '{"id": {"S": "1"}, "name": {"S": "John"}}'

# 查詢
awslocal dynamodb scan --table-name Users

SQS

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 建立佇列
awslocal sqs create-queue --queue-name my-queue

# 發送訊息
awslocal sqs send-message \
    --queue-url http://localhost:4566/000000000000/my-queue \
    --message-body "Hello SQS"

# 接收訊息
awslocal sqs receive-message \
    --queue-url http://localhost:4566/000000000000/my-queue

SNS

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# 建立主題
awslocal sns create-topic --name my-topic

# 訂閱
awslocal sns subscribe \
    --topic-arn arn:aws:sns:us-east-1:000000000000:my-topic \
    --protocol sqs \
    --notification-endpoint arn:aws:sqs:us-east-1:000000000000:my-queue

# 發布訊息
awslocal sns publish \
    --topic-arn arn:aws:sns:us-east-1:000000000000:my-topic \
    --message "Hello SNS"

Terraform 整合

Provider 設定

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
provider "aws" {
  access_key = "test"
  secret_key = "test"
  region     = "us-east-1"

  skip_credentials_validation = true
  skip_metadata_api_check     = true
  skip_requesting_account_id  = true

  endpoints {
    s3       = "http://localhost:4566"
    lambda   = "http://localhost:4566"
    dynamodb = "http://localhost:4566"
    sqs      = "http://localhost:4566"
    sns      = "http://localhost:4566"
    iam      = "http://localhost:4566"
  }
}

部署資源

1
2
terraform init
terraform apply

Python 整合(Boto3)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import boto3

# 建立 LocalStack 客戶端
s3 = boto3.client(
    's3',
    endpoint_url='http://localhost:4566',
    aws_access_key_id='test',
    aws_secret_access_key='test',
    region_name='us-east-1'
)

# 使用 S3
s3.create_bucket(Bucket='my-bucket')
s3.put_object(Bucket='my-bucket', Key='test.txt', Body='Hello')

環境變數方式

1
2
3
4
5
6
7
import os
os.environ['AWS_ENDPOINT_URL'] = 'http://localhost:4566'
os.environ['AWS_ACCESS_KEY_ID'] = 'test'
os.environ['AWS_SECRET_ACCESS_KEY'] = 'test'

import boto3
s3 = boto3.client('s3')  # 自動使用環境變數

CI/CD 整合

GitHub Actions

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
name: Test with LocalStack
on: [push]
jobs:
  test:
    runs-on: ubuntu-latest
    services:
      localstack:
        image: localstack/localstack
        ports:
          - 4566:4566
        env:
          SERVICES: s3,lambda,dynamodb
    steps:
      - uses: actions/checkout@v4
      - name: Run tests
        env:
          AWS_ENDPOINT_URL: http://localhost:4566
        run: |
          pip install boto3 pytest
          pytest tests/          

pytest-localstack

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
# conftest.py
import pytest
import boto3

@pytest.fixture
def s3_client():
    return boto3.client(
        's3',
        endpoint_url='http://localhost:4566',
        aws_access_key_id='test',
        aws_secret_access_key='test'
    )

# test_s3.py
def test_create_bucket(s3_client):
    s3_client.create_bucket(Bucket='test-bucket')
    buckets = s3_client.list_buckets()
    assert 'test-bucket' in [b['Name'] for b in buckets['Buckets']]

進階設定

持久化資料

1
2
3
4
5
6
services:
  localstack:
    environment:
      - PERSISTENCE=1
    volumes:
      - "./localstack-data:/var/lib/localstack"

啟用特定服務

1
2
environment:
  - SERVICES=s3,lambda,dynamodb,sqs

Pro 功能

LocalStack Pro 提供更多服務:

  • ECS、EKS
  • RDS、ElastiCache
  • API Gateway v2
  • Cognito

相關連結

延伸閱讀

comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy