MiniStack: sua AWS local, grátis, com Terraform, bancos reais e mais de 60 serviços

Published on: 2026-09-04
Post image
pt ministack aws open-source docker terraform python devops testes bedrock

Sua aplicação precisa de S3, filas, Lambda e banco. Seu teste não deveria precisar de uma conta na AWS para começar. O MiniStack leva mais de 60 serviços AWS para o ambiente local, com APIs compatíveis, suporte a Terraform e a possibilidade de executar PostgreSQL, Redis e containers de verdade. Código aberto, licença MIT e sem assinatura do emulador.

A proposta resolve uma dor conhecida: você muda uma regra de negócio, mas precisa esperar infraestrutura, disputar uma conta de desenvolvimento ou descobrir por que o pipeline depende de credenciais que só funcionam no notebook de alguém. Com o MiniStack, uma parte importante desse trabalho pode acontecer em http://localhost:4566, usando as ferramentas que o projeto já conhece.

O atrativo está na combinação: emulação de APIs, integração entre serviços e execução real onde ela faz diferença. Dá para criar um bucket com AWS CLI, publicar uma mensagem pelo boto3, provisionar recursos com Terraform e conectar seu driver SQL a um banco iniciado pelo emulador. Só é preciso entender a profundidade de cada implementação: serviço listado não significa reprodução integral da AWS.

Analisei a documentação, o registro de serviços e implementações do repositório em 4 de setembro de 2026, no commit e025978. O pacote declara versão 1.5.7 e classificação Beta; a análise também considera o estado da branch nesse commit, que pode incluir alterações ainda não lançadas. As referências usam esse recorte para o artigo continuar verificável. Metadados do projeto.

O que é o MiniStack — e qual problema ele quer resolver

MiniStack é um emulador local de serviços AWS voltado a desenvolvimento, testes de integração e CI/CD. Você sobe um processo Python ou um container e aponta as chamadas do SDK para o endpoint local. O programa recebe requisições no formato esperado pelos clientes AWS e mantém o estado dos recursos em sua própria máquina.

Isso permite testar mais do que uma função isolada. Uma aplicação pode gravar um objeto, emitir um evento, consumir uma fila e chamar uma função sem criar esses recursos na nuvem. O ciclo fica mais controlável: criar ambiente, carregar dados, executar testes e descartar ou restaurar o estado.

O projeto se posiciona como alternativa livre ao LocalStack. A promessa editorial “free forever” expressa a direção dos mantenedores; o fato verificável hoje é a licença MIT do código analisado, que permite uso, modificação e redistribuição, inclusive comercial, preservando os avisos exigidos. Não há cobrança de licença do MiniStack. Sua máquina, seu runner de CI e eventuais serviços externos continuam tendo seus próprios custos. Licença MIT.

Uma porta para as APIs, vários tipos de execução por trás

O gateway ASGI identifica o serviço a partir de cabeçalhos, assinatura, parâmetros, caminho e hostname. Os módulos são carregados sob demanda. Por isso S3, SQS, DynamoDB e outros clientes compartilham a porta 4566, mesmo usando protocolos diferentes, como JSON, REST e Query/XML. Há suporte a HTTP/2 h2c e opção de HTTPS.

Por trás dessa entrada existem três comportamentos que vale distinguir:

  • Estado e respostas emulados: o MiniStack guarda recursos, valida operações e responde ao SDK. Criar uma VPC nesse modo cria uma representação local da VPC.
  • Execução local de lógica: uma função Lambda Python pode rodar em subprocesso; um workflow pode percorrer estados; uma mensagem pode ser entregue a outro serviço.
  • Infraestrutura auxiliar real: determinados serviços iniciam containers ou usam engines reais, como PostgreSQL, Redis, k3s, Airflow e DuckDB.

A porta única é a entrada das APIs AWS. Conexões SQL, Redis, SFTP e MQTT podem usar portas adicionais. Um banco criado pelo RDS devolve seu próprio endereço e porta; o driver PostgreSQL conecta ali, não na porta do gateway. Isso explica por que “uma porta” não significa “nenhuma configuração de rede”. Arquitetura documentada.

O mapa dos recursos: o que está incluído no projeto

A lista abaixo reúne as famílias da documentação e complementos encontrados no código. Ela cobre o catálogo analisado, sem confundir dezenas de serviços com cobertura de todas as operações existentes na AWS. Em cada família, o importante é o comportamento disponível para o seu teste. Catálogo documentado e registro de serviços no código.

Armazenamento, filas e eventos: a base de uma aplicação distribuída

Guarde arquivos, transporte mensagens e coordene o que acontece depois. Esta família reúne os serviços que fazem os dados circular pela aplicação.

S3, SQS, SNS e Step Functions representados em desenho cartoon por arquivos, envelopes e estados de um workflow

S3

buckets, objetos, listagem, cópia, exclusão em lote, multipart upload, versionamento, tags, CORS, políticas e configurações de criptografia, lifecycle, notificações e replicação. Object Lock inclui retenção e legal hold com aplicação de restrições de exclusão. Armazenar uma configuração não garante reproduzir todo o serviço gerenciado por trás dela.

S3 Tables

tabelas Iceberg e catálogo REST embutido em /iceberg, com arquivos de dados no S3 local. S3 Files: plano de controle para sistemas de arquivos, mount targets, access points e políticas; não equivale a disponibilizar um filesystem de produção.

SQS

filas, atributos, envio e recebimento, mensagens em lote, visibility timeout, filas FIFO, deduplicação e dead-letter queues. Os protocolos Query e JSON são contemplados.

SNS

tópicos, assinaturas, publicação, FIFO, deduplicação e entrega para SQS e Lambda. Também existem operações de aplicações e endpoints de push; isso não transforma o ambiente em um serviço público de entrega para dispositivos.

EventBridge

buses, regras e padrões de eventos, targets, archives e replay. API Destinations podem chamar endpoints HTTP com autenticação configurada; a documentação ressalva que retry de 24 horas, rate limiting e DLQs desse caminho não são reproduzidos.

EventBridge Scheduler

grupos e agendamentos com rate(), cron() e at(), disparando alvos como Lambda, SQS, SNS e Step Functions.

EventBridge Pipes

ciclo de vida dos pipes e execução limitada, no código analisado, à origem DynamoDB Streams e aos destinos SNS ou Step Functions. Não assuma que qualquer combinação aceita pela AWS execute aqui.

Kinesis

streams, shards e records, com roteamento por partition key e limites documentados de tamanho e lote. Firehose: entrega para S3 local, consumo de origem Kinesis e transformação em lote por Lambda; outros tipos de destino têm cobertura mais restrita.

É essa comunicação entre componentes que torna o emulador interessante para integração. Testar a chamada de publicação é uma coisa. Ver uma publicação chegar à fila e ser processada é outra etapa do contrato da aplicação. Escopo de execução dos Pipes.

Step Functions: workflows que percorrem estados de verdade

Step Functions tem um interpretador de Amazon States Language para estados Pass, Task, Choice, Wait, Succeed, Fail, Map e Parallel. A implementação inclui Retry, Catch, callbacks com waitForTaskToken, Activities para workers externos, histórico e execução de workflows aninhados nos caminhos suportados.

Além de JSONPath e funções intrínsecas, o código analisado avalia expressões JSONata. A API TestState permite exercitar um estado isolado, inspecionar a saída e injetar respostas simuladas. SFN_MOCK_CONFIG aceita configuração no formato do Step Functions Local. Isso ajuda a verificar, por exemplo, se uma falha de pagamento entra no estado de compensação e se uma resposta bem-sucedida segue para confirmação, sem depender de um serviço externo.

Para acelerar testes, a configuração interna de escala de espera pode reduzir durações de Wait e retry. Não use esse modo para medir tempos reais. A execução de um workflow ainda depende das integrações implementadas: testar o JSON da máquina e testar todos os seus efeitos são verificações complementares. Implementação de Step Functions.

Bancos, cache, busca e análise de dados

Aqui o foco é onde os dados vivem e como são consultados: bancos transacionais, cache, busca e processamento analítico.

Desenho cartoon de bancos RDS e DynamoDB, cache ElastiCache e consultas Athena e Glue

DynamoDB

tabelas, CRUD, Query, Scan, operações em lote, transações, TTL e configurações auxiliares. O TTL possui processo de expiração em segundo plano; não espere exclusão instantânea no exato segundo do vencimento.

DynamoDB Streams

emite registros de inserção, alteração e remoção, com seleção de imagens e iteradores. A implementação usa um shard sintético por stream; testes locais não medem o comportamento de particionamento real da AWS.

RDS

instâncias e clusters com PostgreSQL, MySQL, MariaDB e variantes Aurora suportadas sobre containers. O endpoint pode aceitar conexões SQL reais. RDS Data API: encaminha SQL aos bancos locais com drivers apropriados. RDS Proxy: cobertura de plano de controle, sem equivalência a um proxy gerenciado em operação.

Aurora DSQL

APIs de clusters e, com DSQL_STRICT=1, PostgreSQL atrás de um proxy que rejeita parte do SQL não suportado pelo DSQL e emula operações como CREATE INDEX ASYNC. A validação tem limites heurísticos; CDC mantém metadados, mas não entrega alterações ao Kinesis.

ElastiCache

containers reais de Redis, Valkey e Memcached. O modo opcional ELASTICACHE_CLUSTER_MODE_REAL=1, com rede Docker configurada, habilita grupos Redis Cluster para exercitar clientes que lidam com slots e redirecionamentos.

OpenSearch Service

gerenciamento de domínios e endpoint simulado por padrão. Com OPENSEARCH_DATAPLANE=1, pode iniciar OpenSearch real; OPENSEARCH_DASHBOARDS=1 adiciona o painel auxiliar. Também pode apontar para um cluster fornecido por você.

Athena

execução de SQL via DuckDB quando instalado, incluindo agregações, joins, CTEs e leitura de arquivos. Sem DuckDB, o resultado é simulado. A compatibilidade de APIs não torna DuckDB idêntico ao engine do Athena.

Glue

catálogo, jobs Python executados localmente e jobs Spark via imagens oficiais do Glue, além de integração com Iceberg. MWAA: o módulo de Airflow pode iniciar Apache Airflow 3 em container e sincronizar DAGs do S3 configurado.

No Aurora PostgreSQL, o comportamento padrão compartilha o banco do cluster entre os membros. Réplicas read-only reais exigem a opção MINISTACK_RDS_PG_CLUSTER_REPLICATION=1 e uma rede Docker. Isso muda o que é válido afirmar em um teste de leitura e escrita: dois endpoints não provam dois processos independentes. Opções de bancos e engines; Implementação do MWAA.

Computação: Lambda, containers, Kubernetes e jobs

Estes componentes executam código ou representam a infraestrutura de execução. O comportamento muda conforme o serviço e o modo habilitado.

Desenho cartoon de Lambda, containers ECS e cluster EKS

Lambda

funções Python e Node.js com execução real, workers aquecidos, versões, aliases, layers, concorrência, Function URLs e configurações de invocação. Event source mappings ligam SQS, Kinesis e DynamoDB Streams às funções.

Runtimes e imagens Lambda

modo Docker com Runtime Interface Emulator, runtimes provided e PackageType=Image. Isso abre caminho para Go, Rust, C++ e imagens próprias, desde que respeitem o contrato do runtime.

Recursos avançados de Lambda

a implementação inclui Durable Functions, callbacks e retomadas; SnapStart inicializa o ambiente ao publicar uma versão, mas não cria um snapshot real; integração de tracing injeta contexto X-Ray nos executores suportados. Lambda MicroVMs é emulação de ciclo de vida e metadados, sem iniciar uma VM real.

Lambda Proxy

encaminha o evento por HTTP a um container que você mantém em execução. Útil para o ciclo local com PHP, Bun, Deno ou outro servidor; esse modo de registrar um container externo não é uma funcionalidade equivalente da AWS Lambda.

ECS

clusters, task definitions, tasks e serviços. RunTask pode iniciar containers reais e injetar metadados de tarefa, endpoint de credenciais e endpoint AWS local.

EKS

criação de cluster com k3s quando Docker está disponível, permitindo uso de kubectl e Helm. Também há operações de nodegroups, addons e access entries; executar k3s não reproduz todos os componentes gerenciados do EKS.

EC2 e EBS

instâncias, imagens, VPCs, subnets, security groups, rotas, interfaces, volumes, snapshots e operações de fleet. Por padrão, instâncias são metadados. Registrar uma AMI associada a uma imagem de container permite executar um container e usar comandos SSM nesse ambiente.

Auto Scaling

grupos, políticas, scheduled actions e lifecycle hooks emulados. Batch: filas e jobs no plano de controle, com conclusão simulada. EMR: representação de clusters e steps, sem executar Hadoop ou Spark por esse serviço.

CodeBuild

projetos e builds simulados por padrão; MINISTACK_CODEBUILD_EXECUTE=1 permite execução com o agente local oficial e Docker, exigindo compartilhamento correto do workspace. ECR: operações de repositório, imagens, manifests Docker V2, tokens e políticas.

Se o teste precisa garantir que a função rodou em container, vale ativar LAMBDA_STRICT=1: a falta de Docker passa a produzir erro em vez de degradar para subprocesso. No EKS, o container k3s usa modo privilegiado. Esses detalhes fazem parte da configuração do laboratório e do acesso que ele terá ao host. Execução Lambda em Docker; Escopo de MicroVMs.

APIs, autenticação, rede e comunicação em tempo real

Esta camada recebe chamadas, identifica usuários e conecta aplicações. APIs HTTP, GraphQL, WebSockets e entrega de conteúdo aparecem neste grupo.

Desenho cartoon de API Gateway, AppSync e Cognito conectando aplicações e usuários

API Gateway REST v1 e HTTP/WebSocket v2

APIs, rotas, métodos, stages, deployments, integrações com Lambda, HTTP e mocks. Há execução de tráfego, CORS, authorizers nos caminhos suportados e gerenciamento de conexões WebSocket.

URLs previsíveis

o caminho /_aws/execute-api/{apiId}/{stage}/{path} facilita acesso sem depender de DNS personalizado. A tag ms-custom-id fixa IDs de API; o nome legado ls-custom-id não é intercambiável.

AppSync

APIs GraphQL, schemas e resolvers; o código analisado valida schemas com graphql-core e executa resolvers APPSYNC_JS em workers Node, com fontes NONE, HTTP, DynamoDB e Lambda. A cobertura deve ser validada por operação; não é garantia de todo o GraphQL/AppSync.

AppSync Events

publicação HTTP, canais e conexões WebSocket, com opção de exigir autenticação local. É uma superfície própria; não deve ser confundida com cobertura automática de todas as subscriptions GraphQL.

Cognito

User Pools e Identity Pools, fluxos de autenticação e integração com aplicações. Há fluxo CUSTOM_AUTH com triggers Lambda e verificação TOTP real. Outros atalhos continuam presentes, como códigos fixos em fluxos de confirmação; não é um provedor de identidade para produção.

ELBv2/ALB

listeners, regras, target groups, encaminhamento para Lambda, respostas fixas, redirects e fluxo OIDC implementado. A cobertura de ações e destinos continua sendo específica do emulador.

Route 53 e Cloud Map

zonas, registros e service discovery. Configurar registros localmente não publica DNS autoritativo na internet.

CloudFront e CloudFront KeyValueStore

distribuições, políticas, invalidações, configurações de SaaS Manager e armazenamento chave/valor com ETags. CloudFront Functions guarda código e versões de configuração, sem executar JavaScript na borda; o emulador não cria uma CDN mundial.

EFS

APIs de sistemas de arquivos, mount targets e access points emulados. Transfer Family: listener SFTP real com arquivos no S3 local e autenticação por chaves SSH, usando uma porta adicional.

Amplify Gen 2 aparece entre as integrações documentadas, combinando Cognito, AppSync, S3 e Lambda. Antes de assumir compatibilidade total, rode o schema, os resolvers e o fluxo de login do seu aplicativo. O README tem trechos de épocas diferentes; para os resolvers JavaScript e AppSync Events, a análise também conferiu a implementação. AppSync no código; AppSync Events.

Segurança, configuração, observabilidade e governança

Quem pode acessar, onde guardar configurações e como observar o sistema: os componentes abaixo ajudam a controlar e acompanhar o ambiente.

Desenho cartoon de IAM e KMS, Secrets Manager e CloudWatch com escudo, caixa e monitor

IAM e STS

identidades, roles, políticas e sessões. A opção AUTH=true ativa verificações IAM implementadas pelo projeto. No padrão, não use uma chamada bem-sucedida como prova de que a política de produção está correta.

KMS

chaves, aliases, criptografia, assinaturas, HMAC e recursos de chaves multirregião. Há operações criptográficas reais, mas isso não representa isolamento por HSM nem a fronteira de segurança da AWS.

Secrets Manager e SSM Parameter Store

segredos, parâmetros e tipos String, SecureString e StringList. O SSM também participa do caminho de comandos em instâncias locais compatíveis.

AppConfig e AppConfigData

versões de configuração, deployments e recuperação por sessões com rotação de tokens.

CloudWatch Metrics e Logs

métricas, alarmes, grupos, streams, eventos de log e caminhos de consulta/Live Tail suportados. CloudTrail: trilha local em memória com gravação opt-in por CLOUDTRAIL_RECORDING=1.

SES e SES v2

identidades, templates e e-mails inspecionáveis localmente. Por padrão, mensagens ficam em memória; configurar SMTP_HOST permite encaminhamento a um servidor SMTP.

ACM

certificados e registros de validação emulados, com emissão automática no ambiente. WAF v2: ACLs, conjuntos de IP e regras no plano de controle; WAF Classic/Regional tem cobertura mínima. Isso não torna o gateway um firewall equivalente à AWS.

Organizations e Account

organizações, unidades organizacionais, contas e configurações regionais. Resource Groups e Resource Groups Tagging API: agrupamento, consulta e gerenciamento de tags.

AWS Config

regras, recorders, canais de entrega e consultas de status/conformidade. Cloud Control API: operações genéricas de recursos para ferramentas que usam esse contrato.

AWS Backup

vaults, planos e jobs com conclusão simulada. Cost & Usage Reports: gerenciamento de definições de relatórios, não apuração real de uma fatura AWS. Inspector2: findings determinísticos simulados; não executa uma auditoria real de vulnerabilidades.

Também existem emulações de IMDS v1/v2, ECS Task Metadata v4 e credenciais de containers ECS. Elas ajudam a testar aplicações que dependem da cadeia padrão de credenciais e dos metadados do ambiente. É diferente de simplesmente preencher duas variáveis de acesso no código. Roteamento e configuração de autenticação.

IoT, Kafka, mensagens e mídia: os detalhes que ficam fora do básico

Dispositivos, brokers e protocolos especializados têm requisitos próprios. Neste grupo, preste atenção a quais serviços executam um backend e quais mantêm apenas metadados.

Desenho cartoon de sensor IoT Core, mensagens MSK e transferência de arquivos

IoT Core

recursos de dispositivos, certificados e políticas, MQTT 3.1.1/5.0 sobre WebSocket e listener MQTT com TLS na porta 8883, conforme as dependências e a configuração. O certificado de cliente é opcional no comportamento local documentado, e políticas IoT não têm a mesma aplicação da AWS.

IoT Jobs

APIs de controle e de dispositivo, estados das execuções e controle de concorrência por versão. Nem todas as transições e timeouts reais são automatizados.

MSK

clusters, configurações e bootstrap brokers no plano de controle. Para produzir e consumir Kafka, forneça um broker real, como Kafka ou Redpanda, e configure MINISTACK_MSK_BOOTSTRAP. O protocolo Kafka não é emulado.

Amazon MQ

recursos e operações de gerenciamento, sem broker real iniciado pelo serviço.

MediaConnect

representação de flows e operações de consulta, sem backend real de streaming ou transcodificação.

Essa distinção evita uma armadilha comum: o SDK receber um endereço ou status válido não prova que existe um mecanismo de execução por trás. Em MSK você traz o broker; em ElastiCache, o projeto pode criá-lo; em MediaConnect, a proposta do módulo é representar o plano de controle. Escopo do MediaConnect.

Bedrock local: use o contrato da AWS com um modelo no seu ambiente

Nesta parte entram inferência, agentes e processamento de áudio. A diferença entre resposta simulada e execução de um modelo é central para entender o que seu teste valida.

Desenho cartoon distinguindo modelos locais, mocks e o endpoint Bedrock

A família Bedrock cobre catálogo e gerenciamento de modelos, perfis de inferência, guardrails, jobs e outras operações. Bedrock Runtime implementa caminhos como Converse, InvokeModel e versões com streaming. Bedrock Agent e Agent Runtime acrescentam agentes, knowledge bases, ingestão, sessões, flows e operações de recuperação. AgentCore inclui ciclo de vida de runtimes e endpoints.

Por padrão, as respostas de inferência são mocks determinísticos, com formatos compatíveis com famílias de modelos. Isso é útil para testar parsing, campos obrigatórios e tratamento de streaming. Para gerar texto real, MINISTACK_BEDROCK_PROXY_URL aponta para um backend compatível com chat completions, como Ollama, llama.cpp ou vLLM. O MiniStack traduz a chamada de entrada e a resposta.

No Docker Desktop, com o backend já disponível no host na porta 11434, a configuração documentada usa:

docker run --rm --name ministack-bedrock \
  -p 127.0.0.1:4566:4566 \
  -e MINISTACK_BEDROCK_PROXY_URL=http://host.docker.internal:11434/ \
  ministackorg/ministack:1.5.7

Esse comando é uma alternativa à instância anterior: duas instâncias não podem ocupar a mesma porta. No Linux, ajuste a resolução e o acesso ao host, por exemplo com --add-host host.docker.internal:host-gateway quando aplicável. O identificador enviado ao backend precisa corresponder a um modelo que ele consiga atender; usar um nome de Claude não instala nem executa Claude localmente.

Existem limites que afetam diretamente o teste:

  • Falha do proxy pode voltar ao mock. A implementação documenta fallback quando a conexão falha. Verifique a saída e os logs; sucesso HTTP não garante que seu LLM respondeu.
  • Knowledge bases não equivalem a um sistema vetorial completo. A recuperação analisa documentos ingeridos com pontuação lexical, sem embeddings.
  • Agentes não reproduzem toda a orquestração. InvokeAgent usa resposta predefinida; a invocação de AgentCore é um echo determinístico no escopo analisado.
  • Guardrails têm cobertura parcial. Políticas determinísticas de palavras, regex e certos dados sensíveis podem ser aplicadas; avaliações que dependem de modelos, como tópicos e grounding, não são reproduzidas.
  • Contagem de tokens pode ser aproximada. Não use o mock para comparar custo, latência ou qualidade de um modelo real.

O Transcribe merece o mesmo cuidado: simula jobs batch, lê referências de mídia, grava resultados e pode emitir eventos de conclusão, mas não reconhece fala. A transcrição é texto determinístico. Serve para testar o pipeline que reage ao job; não para medir acurácia de áudio. Runtime do Bedrock; Limites dos agentes; Transcribe.

Subindo o ambiente: comece com o menor exemplo útil

Com os grupos de serviços em mente, vamos montar o ambiente: primeiro subir o MiniStack, depois chamar as APIs, adicionar bancos e automatizar os testes.

Desenho cartoon de um desenvolvedor organizando Docker, Python e Terraform para testes locais

Para instalação Python, o pacote analisado exige Python 3.10 ou superior. Em um ambiente virtual:

python3 -m venv .venv
source .venv/bin/activate
python -m pip install ministack==1.5.7
ministack

Com Docker, uma instância simples pode ser iniciada assim:

docker run --rm --name ministack-dev \
  -p 127.0.0.1:4566:4566 \
  ministackorg/ministack:1.5.7

Em outro terminal, com AWS CLI instalado, confira a saúde e faça as primeiras chamadas. As credenciais abaixo são locais, não chaves de uma conta real:

curl --fail http://localhost:4566/_ministack/health

export AWS_ACCESS_KEY_ID=test
export AWS_SECRET_ACCESS_KEY=test
export AWS_DEFAULT_REGION=us-east-1
export AWS_EC2_METADATA_DISABLED=true

aws --endpoint-url=http://localhost:4566 s3 mb s3://ministack-demo
aws --endpoint-url=http://localhost:4566 sqs create-queue --queue-name pedidos
aws --endpoint-url=http://localhost:4566 sts get-caller-identity

A imagem full adiciona dependências como DuckDB e drivers de banco. Para esse cenário, use ministackorg/ministack:full ou instale ministack[full]==1.5.7 no Python. A tag full pode avançar; em CI, fixe uma versão publicada apropriada ou o digest da imagem que você validou. O README apresenta números diferentes de tamanho entre trechos, então não trato tamanho, memória ou tempo de boot anunciados como benchmark reproduzido.

Um exemplo Python que verifica armazenamento e mensageria

Com o emulador rodando, instale boto3 no ambiente do seu script. Este exemplo cria recursos com nome único, grava e lê um objeto, envia e confirma uma mensagem e limpa os recursos ao terminar. O endpoint fica explícito para que o teste use o ambiente local.

import json
from uuid import uuid4

import boto3
from botocore.config import Config


def client(service):
    return boto3.client(
        service,
        endpoint_url="http://localhost:4566",
        region_name="us-east-1",
        aws_access_key_id="test",
        aws_secret_access_key="test",
        config=Config(s3={"addressing_style": "path"}),
    )


s3 = client("s3")
sqs = client("sqs")
suffix = uuid4().hex[:12]
bucket = f"pedidos-{suffix}"
queue_url = None
created_bucket = False

try:
    s3.create_bucket(Bucket=bucket)
    created_bucket = True
    queue_url = sqs.create_queue(QueueName=f"pedidos-{suffix}")["QueueUrl"]
    payload = json.dumps({"pedido_id": "p-123", "total": 149.90}).encode()

    s3.put_object(Bucket=bucket, Key="pedido.json", Body=payload)
    response = s3.get_object(Bucket=bucket, Key="pedido.json")
    with response["Body"] as body:
        assert body.read() == payload

    sqs.send_message(QueueUrl=queue_url, MessageBody=payload.decode())
    messages = sqs.receive_message(
        QueueUrl=queue_url, MaxNumberOfMessages=1, WaitTimeSeconds=5
    ).get("Messages", [])
    assert messages, "A mensagem não chegou à fila local"
    assert json.loads(messages[0]["Body"])["pedido_id"] == "p-123"
    sqs.delete_message(
        QueueUrl=queue_url, ReceiptHandle=messages[0]["ReceiptHandle"]
    )
    print("S3 e SQS responderam ao fluxo de integração local.")
finally:
    if queue_url is not None:
        sqs.delete_queue(QueueUrl=queue_url)
    if created_bucket:
        s3.delete_object(Bucket=bucket, Key="pedido.json")
        s3.delete_bucket(Bucket=bucket)

O exemplo valida chamadas de S3 e SQS; ele não configura notificação automática de S3 para a fila. Quando o contrato do produto depender de um evento, inclua a configuração de notificação ou o vínculo entre serviços e teste também essa entrega. Separar essas duas expectativas torna a falha muito mais fácil de interpretar.

Docker Compose, persistência e bancos reais

O Compose abaixo usa a imagem completa, guarda estado e objetos e disponibiliza o socket Docker para serviços que iniciam containers auxiliares. A rede tem nome explícito para que os componentes possam se encontrar:

services:
  ministack:
    image: ministackorg/ministack:full
    ports:
      - "127.0.0.1:4566:4566"
    environment:
      DOCKER_NETWORK: ministack-dev
      PERSIST_STATE: "1"
      STATE_DIR: /data/state
      S3_PERSIST: "1"
      S3_DATA_DIR: /data/s3
      RDS_PERSIST: "1"
      MINISTACK_RDS_PUBLIC_ENDPOINT: "1"
      MINISTACK_HOST: localhost
      LAMBDA_EXECUTOR: docker
      ATHENA_ENGINE: duckdb
    volumes:
      - ministack-data:/data
      - /var/run/docker.sock:/var/run/docker.sock
    networks:
      - dev

networks:
  dev:
    name: ministack-dev

volumes:
  ministack-data:

Aqui, MINISTACK_RDS_PUBLIC_ENDPOINT=1 atende drivers de banco executados no host: o RDS informa endereço e porta publicados. Para aplicações dentro de containers, ajuste o hostname e a rede. localhost dentro de um container aponta para o próprio container. Não é um endereço universal para o serviço MiniStack.

O socket permite ao emulador controlar containers no seu daemon Docker. Ele só é necessário quando você quer essa execução auxiliar. O primeiro uso pode baixar imagens, e bancos, Kubernetes e modelos de IA acrescentam consumo real de CPU, RAM e disco.

PERSIST_STATE conserva o estado dos serviços; S3_PERSIST conserva objetos; RDS_PERSIST troca armazenamento temporário por volumes dos bancos. Não são opções equivalentes. Escrita atômica de estado também não equivale a durabilidade completa diante de qualquer interrupção: o salvamento documentado ocorre no encerramento do processo.

Para criar PostgreSQL, depois de subir esse Compose e instalar boto3 e psycopg2-binary, o fluxo abaixo aguarda a instância ficar disponível antes de conectar. Execute em um ambiente de demonstração vazio:

import boto3
import psycopg2

rds = boto3.client(
    "rds",
    endpoint_url="http://localhost:4566",
    region_name="us-east-1",
    aws_access_key_id="test",
    aws_secret_access_key="test",
)
rds.create_db_instance(
    DBInstanceIdentifier="blog-postgres",
    DBInstanceClass="db.t3.micro",
    Engine="postgres",
    MasterUsername="appuser",
    MasterUserPassword="local-dev-password",
    DBName="appdb",
    AllocatedStorage=20,
)
rds.get_waiter("db_instance_available").wait(
    DBInstanceIdentifier="blog-postgres",
    WaiterConfig={"Delay": 2, "MaxAttempts": 90},
)
instance = rds.describe_db_instances(
    DBInstanceIdentifier="blog-postgres"
)["DBInstances"][0]
endpoint = instance["Endpoint"]

connection = psycopg2.connect(
    host=endpoint["Address"],
    port=endpoint["Port"],
    dbname="appdb",
    user="appuser",
    password="local-dev-password",
    connect_timeout=10,
)
try:
    with connection.cursor() as cursor:
        cursor.execute("SELECT 40 + 2")
        assert cursor.fetchone()[0] == 42
finally:
    connection.close()

Esse caminho exercita SQL real. A classe db.t3.micro é um parâmetro da API emulada; não significa que seu container tenha o mesmo hardware, desempenho ou disponibilidade da instância correspondente na AWS. O exemplo deixa a instância criada para inspeção; remova-a pelo RDS local quando terminar. Endpoints RDS.

Terraform: mantenha os recursos, direcione o provider

A documentação declara suporte aos providers AWS v5 e v6. O ajuste central é configurar credenciais locais, endpoints e opções que evitam verificações contra a nuvem real. Para um exemplo só com S3 e SQS, um main.tf pode ser:

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 6.0"
    }
  }
}

provider "aws" {
  region                      = "us-east-1"
  access_key                  = "test"
  secret_key                  = "test"
  s3_use_path_style           = true
  skip_credentials_validation = true
  skip_metadata_api_check     = true
  skip_requesting_account_id  = true

  endpoints {
    s3  = "http://localhost:4566"
    sqs = "http://localhost:4566"
    sts = "http://localhost:4566"
  }
}

resource "aws_s3_bucket" "uploads" {
  bucket = "ministack-terraform-uploads"
}

resource "aws_sqs_queue" "pedidos" {
  name = "ministack-terraform-pedidos"
}
terraform init
terraform plan
terraform apply
# Ao terminar, neste diretório de demonstração:
terraform destroy

Adicione endpoints para todos os serviços utilizados pelo seu módulo, incluindo data sources e operações auxiliares. Não copie um provider que redireciona só S3 para um projeto que também usa IAM, EC2 e RDS. Preserve o lockfile e o estado local desse laboratório separados dos ambientes reais.

O teste de compatibilidade útil inclui criar, consultar, atualizar, aplicar novamente e destruir. Uma operação Create funcionar não garante que o provider consiga fazer o Read seguinte sem diferenças permanentes. Esse é um dos motivos para o changelog conter correções específicas de convergência do Terraform. Integrações de infraestrutura como código.

CloudFormation, CDK, Pulumi e Testcontainers

CloudFormation tem operações de stacks, change sets, exports, parâmetros, condições e funções intrínsecas, incluindo referências entre stacks. Templates JSON e YAML são aceitos, e existe implantação assíncrona com status e rollback. A cobertura de tipos de recurso é parcial; não basta um serviço existir para todo recurso CloudFormation dele estar implementado.

Para CDK, a documentação usa AWS_ENDPOINT_URL=http://localhost:4566 junto das credenciais de teste. Para Pulumi, configura endpoints no provider AWS. Os dois dependem da cobertura dos recursos que o programa gera; confirme o endpoint no processo que efetivamente faz o deploy.

O repositório também oferece exemplos de Testcontainers para Java, Go e Python. A vantagem é o teste controlar o ciclo de vida do container: inicia o ambiente, espera o health check, usa o endpoint e encerra ao terminar. Isso ajuda a reproduzir o mesmo cenário no notebook e no runner de CI. Exemplos de Testcontainers.

Várias contas e regiões sem multiplicar o ambiente

Uma access key numérica de 12 dígitos representa o ID da conta local. Chaves como test usam a conta padrão, normalmente 000000000000. A região vem do escopo da assinatura SigV4 usada pelo SDK. Assim você pode exercitar recursos homônimos em contextos diferentes.

AWS_ACCESS_KEY_ID=111111111111 AWS_SECRET_ACCESS_KEY=test \
  aws --endpoint-url=http://localhost:4566 --region us-east-1 \
  sqs create-queue --queue-name pedidos

AWS_ACCESS_KEY_ID=222222222222 AWS_SECRET_ACCESS_KEY=test \
  aws --endpoint-url=http://localhost:4566 --region us-east-1 \
  sqs create-queue --queue-name pedidos

AWS_ACCESS_KEY_ID=111111111111 AWS_SECRET_ACCESS_KEY=test \
  aws --endpoint-url=http://localhost:4566 --region eu-west-1 \
  sqs create-queue --queue-name pedidos

Esses três contextos não deveriam disputar a mesma fila. Mas o README registra exceções regionais para S3 e Aurora DSQL, que compartilham estado entre regiões dentro da conta. Serviços globais, como IAM, STS, Route 53, CloudFront e Organizations, exigem leitura própria desse escopo. E conta local é organização de estado para testes, não uma fronteira de segurança entre usuários hostis. Escopo e exceções multirregião.

Automação de testes: saúde, reset, inspeção e scripts de inicialização

A API interna facilita preparar o ambiente e observar o que aconteceu. Estes endpoints são especialmente úteis em testes:

# Saúde do ambiente
curl --fail http://localhost:4566/_ministack/health

# Inspecionar e-mails e mensagens locais
curl --fail http://localhost:4566/_ministack/ses/messages
curl --fail http://localhost:4566/_ministack/sqs/messages

# Apagar o estado de TODOS os serviços e contas desta instância
curl --fail -X POST http://localhost:4566/_ministack/reset

# Apagar o estado e executar novamente os scripts de inicialização
curl --fail -X POST 'http://localhost:4566/_ministack/reset?init=1'

O reset é global para a instância. Se dois jobs compartilham o mesmo processo, separar access keys não protege um deles do reset acionado pelo outro. Para paralelismo, prefira instâncias independentes por job ou coordene explicitamente a limpeza dos recursos. Os endpoints de inspeção ajudam a verificar conteúdo, visibilidade e tentativas sem depender só dos logs da aplicação.

Scripts .sh e .py podem rodar antes da inicialização ou após o serviço ficar pronto, nos diretórios nativos e nos caminhos compatíveis com LocalStack. Para criar buckets e filas via API, use a fase ready.d. Os scripts recebem endpoint e credenciais locais; nomes ordenados permitem carregar primeiro recursos e depois dados de exemplo.

Existe ainda /_ministack/config para configurações de execução suportadas, além de filtros de serviços por SERVICES, nível de log, customização de portas, TLS e prefixo de registro privado para imagens auxiliares. Consulte a opção do recurso que você vai executar: “instalou o pacote” e “habilitou todos os backends” são etapas diferentes. API interna; Inicialização automatizada.

Quando vale adotar — e o que ainda precisa chegar à AWS

MiniStack é particularmente útil para onboarding de times, desenvolvimento de backends orientados a eventos, testes de SDKs, validação de módulos Terraform e integração de aplicações que dependem de armazenamento, filas, bancos e funções. O melhor primeiro passo é escolher um fluxo real do produto e reproduzi-lo do começo ao fim.

Eu avaliaria a adoção com perguntas concretas: a aplicação grava e recupera o mesmo dado? O evento chega ao destino? A função falha como esperado? O provider converge? O retry acontece? O teste distingue um backend indisponível de um mock bem-sucedido? A resposta vale mais que contar quantos nomes aparecem no catálogo.

O ambiente local não mede latência entre regiões, escalabilidade da infraestrutura gerenciada, custo de produção, todos os limites de serviço ou a totalidade das políticas IAM. Complete os testes locais com uma etapa controlada na AWS para os contratos que dependem dessas propriedades. Isso permite reservar a nuvem para as verificações que realmente precisam dela.

O ecossistema já inclui integrações comunitárias como StackPort, um painel para inspecionar recursos, integração com .NET Aspire e OpenArchFlow, voltado a diagramas de arquitetura. São projetos externos, não funcionalidades de interface embutidas no MiniStack. Integrações comunitárias.

Como contribuir e por que a proposta importa

O código organiza as implementações por serviço em Python. O roteiro de contribuição envolve criar o handler, registrar o serviço, acrescentar o roteamento e escrever testes. Para quem encontrou uma incompatibilidade de SDK ou Terraform, uma reprodução pequena com a operação, versão do cliente e resposta esperada costuma ser uma contribuição valiosa. Guia de contribuição.

O MiniStack reduz a distância entre escrever código que usa AWS e conseguir testá-lo. Uma instalação local pode reunir contratos de APIs, eventos e recursos de infraestrutura que antes exigiam mais configuração espalhada pelo time. O código aberto permite inspecionar o comportamento e corrigir justamente o pedaço que seu projeto precisa.

A proposta fica mais forte quando usada com expectativas precisas: comece por um fluxo, habilite os componentes reais necessários e confirme os limites do serviço. Se a sua aplicação depende de S3, SQS, Lambda ou PostgreSQL, já existe um ponto de partida concreto para colocar o ambiente de desenvolvimento sob seu controle.

Referências e escopo da análise

Fontes primárias consultadas no repositório do projeto. Os exemplos foram escritos para explicar configuração e uso; esta análise não é um benchmark nem uma certificação de paridade com a AWS. Recursos da branch podem anteceder uma imagem publicada.