Tous les articles
Mer. 8 avril 2026 · 3 min de lecture

🪣 LocalStack et Ministack : un AWS complet sur sa machine

LocalStack

📚 Introduction

Travailler avec AWS au quotidien pose deux problèmes récurrents : les coûts qui s’accumulent sur les environnements de dev et de CI, et la dépendance au réseau pour la moindre boucle de test. Tester une intégration S3 ou un consumer SQS depuis sa machine en TER ou en avion devient un calvaire.

LocalStack émule la majorité des services AWS dans un seul conteneur Docker. Ministack, plus récent, suit la même philosophie en visant un footprint encore plus léger et une compatibilité ciblée sur les services les plus utilisés (S3, SQS, SNS, DynamoDB, Lambda).

Dans les deux cas, l’idée est identique : pointer le SDK AWS sur un endpoint local, et continuer à coder comme si l’on parlait au vrai AWS.

🚀 Démarrer un LocalStack en 30 secondes

LocalStack se lance avec un simple docker-compose.yml :

services:
  localstack:
    image: localstack/localstack:latest
    ports:
      - '4566:4566'
    environment:
      - SERVICES=s3,sqs,sns,dynamodb,lambda
      - DEBUG=0
      - PERSISTENCE=1
    volumes:
      - ./.localstack:/var/lib/localstack
      - /var/run/docker.sock:/var/run/docker.sock

Un docker compose up -d plus tard, on dispose d’une API AWS écoutant sur http://localhost:4566. Toutes les opérations classiques fonctionnent :

aws --endpoint-url=http://localhost:4566 s3 mb s3://invoices
aws --endpoint-url=http://localhost:4566 sqs create-queue --queue-name billing
aws --endpoint-url=http://localhost:4566 dynamodb list-tables

🪶 Ministack : la version “tactique”

Ministack vise une niche complémentaire : un binaire unique, démarrage en moins d’une seconde, périmètre limité aux services les plus courants. C’est typiquement le tooling à favoriser dans une CI où chaque seconde compte.

ministack up --services s3,sqs --port 4566

Le contrat d’API est suffisamment proche de celui de LocalStack pour que la majorité des SDK AWS ne voient pas la différence. C’est l’option que je sélectionne sur les pipelines GitHub Actions, là où LocalStack alourdit le temps de boot.

🧰 Exemple complet : S3 + SQS depuis Laravel

Voyons un cas pratique : une application Laravel qui dépose un fichier sur S3, puis publie un message SQS pour déclencher un traitement asynchrone. Configuration dans config/filesystems.php :

'disks' => [
	's3' => [
		'driver' => 's3',
		'key' => env('AWS_ACCESS_KEY_ID'),
		'secret' => env('AWS_SECRET_ACCESS_KEY'),
		'region' => env('AWS_DEFAULT_REGION', 'eu-west-3'),
		'bucket' => env('AWS_BUCKET'),
		'endpoint' => env('AWS_ENDPOINT'),
		'use_path_style_endpoint' => true,
	],
],

Côté .env.local, on cible LocalStack :

AWS_ACCESS_KEY_ID=test
AWS_SECRET_ACCESS_KEY=test
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=invoices
AWS_ENDPOINT=http://localhost:4566
SQS_QUEUE=http://localhost:4566/000000000000/billing

Et un job Laravel qui combine les deux :

final class UploadInvoiceAndNotify
{
	public function handle(Invoice $invoice): void
	{
		Storage::disk('s3')->put(
			"invoices/{$invoice->id}.pdf",
			$invoice->renderPdf()
		);
 
		BillingQueue::push(new InvoiceUploaded($invoice->id));
	}
}

Tout ce qui passait avant par les serveurs AWS passe maintenant par votre Docker local. Aucune ligne de code applicatif à toucher entre dev et production : seules les variables d’environnement changent.

🧪 Intégration dans la CI

Sur GitHub Actions :

services:
  localstack:
    image: localstack/localstack:latest
    ports:
      - 4566:4566
    env:
      SERVICES: s3,sqs

Les tests d’intégration s’exécutent contre une vraie API AWS (locale), pas contre un mock partiel. Le delta de fiabilité est significatif : on attrape des erreurs de signature, de permissions IAM ou de format de message qu’un mock laisserait passer.

⚠️ Limites à connaître

  • Tous les services AWS ne sont pas couverts : LocalStack Pro (payant) débloque RDS, EKS, AppSync… la version Community se concentre sur les services les plus utilisés.
  • Le comportement d’IAM est partiel par défaut. Pour tester les permissions à fond, activer ENFORCE_IAM=1.
  • Les latences réseau de production ne se reproduisent pas en local : restez prudents sur les hypothèses de performance.

🎉 Conclusion

LocalStack reste l’option par défaut quand on veut couvrir un maximum de services AWS. Ministack se distingue sur les CI et les besoins ciblés où le temps de boot compte plus que la couverture fonctionnelle.

Dans les deux cas, la règle d’or est la même : faites en sorte que votre code n’ait jamais à savoir s’il parle à LocalStack, à Ministack ou au vrai AWS. Une simple variable d’environnement doit suffire à basculer.

🔗 Liens utiles