How to Build a Zero-Cost Local AWS Development Environment with Floci in 10 Minutes

15 views 0 likes 0 comments 21 minutesOriginalTutorial

A practical step-by-step guide for Java developers to replace expensive AWS testing with a local Floci simulator. Learn to run S3, DynamoDB, and SQS on localhost:4566, configure AWS SDK v2, and integrate with Testcontainers for fast, offline debugging.

#Local Development # AWS Simulator # Docker # Java # Spring Boot # Microservices # DevOps # Floci
How to Build a Zero-Cost Local AWS Development Environment with Floci in 10 Minutes

Still Paying for AWS During Local Testing? Run a Full Local Cloud Environment for Free

When writing business logic, you've likely faced this scenario:

Your microservices rely on S3 for file storage, DynamoDB for state tracking, and SQS for peak shaving. But during development, you always connect to a real AWS account. Not only does it cost money, but debugging offline or running CI pipelines becomes a hassle. Some developers use Mock Beans to patch it, but mocks often diverge from real behavior, leading to bugs only discovered in production.

Today, I'll show you how to use an open-source tool called Floci to spin up a complete AWS simulator locally with one command. No AWS account, no tokens, no fees—just Docker. The entire environment uses less than 20MB of RAM and starts in milliseconds. Follow along, and you'll move S3, DynamoDB, SQS, and dozens of other services to localhost:4566, doubling your local dev & test efficiency.


Prerequisites

  • Docker (Docker Compose V2 recommended): Floci runs containerized, so Docker is mandatory.
  • JDK 17+: The Java examples in this guide use AWS SDK v2.
  • AWS CLI (optional): Handy for quickly verifying service connectivity.
  • Basic Knowledge: Familiarity with AWS SDK fundamentals is sufficient.

Why Docker? Because Floci's services like Lambda, RDS, and ECS run in real Docker containers, not shallow mocks. This guarantees high consistency with real AWS services, which is exactly why it's more reliable than older Mock Bean approaches.


Step 1: Start Floci

The recommended approach is Docker Compose for clear configuration and easy management. Create a compose.yaml at your project root:

yaml 复制代码
services:
  floci:
    image: floci/floci:latest
    ports:
      - "4566:4566"
    environment:
      - FLOCI_STORAGE_MODE=hybrid   # Keeps data after restart, recommended for dev

Here, FLOCI_STORAGE_MODE=hybrid means data primarily resides in memory for fast read/write, while asynchronously flushing to disk every 5 seconds. This ensures your buckets and tables survive container restarts. If you're running CI pipelines, switch it to memory.

Start it up:

bash 复制代码
docker compose up -d

After a few seconds, Floci will listen on localhost:4566. Verify it:

bash 复制代码
curl http://localhost:4566/_floci/ui

A non-empty response means the service is ready. Visiting http://localhost:4566/_floci/ui in your browser opens Floci's built-in Web Console for visualizing local resources.

Port Note: 4566 is Floci's unified gateway. All AWS service API requests route through here and are dispatched internally. This is far more convenient than the old days where each service consumed its own port.


Step 2: Configure AWS Clients to Point Locally

Whether using CLI, SDK, or Terraform, the core idea remains the same: point the endpoint locally and provide a set of valid (but dummy) credentials.

Manual Configuration:

bash 复制代码
export AWS_ENDPOINT_URL=http://localhost:4566
export AWS_DEFAULT_REGION=us-east-1
export AWS_ACCESS_KEY_ID=test
export AWS_SECRET_ACCESS_KEY=test

Why can credentials be arbitrary? Per the Floci README and multi-account docs: by default Floci does not verify SigV4 signatures, so any non-empty Access Key / Secret works (e.g. test/test). To enforce signature checks, set FLOCI_AUTH_VALIDATE_SIGNATURES=true. The default is fine for local development.

After configuring, test it by creating an S3 bucket via CLI:

bash 复制代码
aws --endpoint-url http://localhost:4566 s3 mb s3://my-dev-bucket
aws --endpoint-url http://localhost:4566 s3 ls
## Output should include my-dev-bucket

If it outputs normally, your local environment is ready.


Step 3: Java SDK Practical Demo

Running CLI is just the start. Let's use a complete Java example to operate S3, DynamoDB, and SQS simultaneously, simulating a flow: "User uploads image → Thumbnail task queued → Task status saved to DB".

The most critical point: Java SDK must use both endpointOverride and credentialsProvider. Many beginners trip here—forgetting to override the endpoint causes the SDK to still hit real AWS.

java 复制代码
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.sqs.SqsClient;
import software.amazon.awssdk.services.dynamodb.model.*;
import software.amazon.awssdk.services.sqs.model.*;

import java.net.URI;
import java.util.Map;

public class FlociDemo {

    private static final String ENDPOINT = "http://localhost:4566";
    private static final String REGION = "us-east-1";
    private static final StaticCredentialsProvider CRED =
        StaticCredentialsProvider.create(
            AwsBasicCredentials.create("test", "test"));

    public static void main(String[] args) {
        // 1. Create DynamoDB client & table (status table)
        var dynamo = DynamoDbClient.builder()
            .endpointOverride(URI.create(ENDPOINT))
            .region(Region.of(REGION))
            .credentialsProvider(CRED)
            .build();

        dynamo.createTable(CreateTableRequest.builder()
            .tableName("thumbnail-tasks")
            .billingMode(BillingMode.PAY_PER_REQUEST)
            .attributeDefinitions(
                AttributeDefinition.builder()
                    .attributeName("taskId").attributeType(ScalarAttributeType.S).build())
            .keySchema(
                KeySchemaElement.builder()
                    .attributeName("taskId").keyType(KeyType.HASH).build())
            .build());

        // 2. Create SQS queue (task queue)
        var sqs = SqsClient.builder()
            .endpointOverride(URI.create(ENDPOINT))
            .region(Region.of(REGION))
            .credentialsProvider(CRED)
            .build();

        var queueUrl = sqs.createQueue(
            CreateQueueRequest.builder().queueName("thumbnail-jobs").build() ).queueUrl();

        // 3. Simulate: Upload file desc + queue task + save status
        String taskId = "task-001";
        String fileName = "photo.jpg";

        sqs.sendMessage(SendMessageRequest.builder()
            .queueUrl(queueUrl)
            .messageBody(fileName).build());

        dynamo.putItem(PutItemRequest.builder()
            .tableName("thumbnail-tasks")
            .item(Map.of("taskId", AttributeValue.builder().s(taskId).build(),
                         "status", AttributeValue.builder().s("PENDING").build(),
                         "file",   AttributeValue.builder().s(fileName).build()))
            .build());

        // 4. Verify: Query table & messages
        var scanResult = dynamo.scan(ScanRequest.builder().tableName("thumbnail-tasks").build());
        System.out.println("[DynamoDB] Record count: " + scanResult.count());

        var msgResult = sqs.receiveMessage(ReceiveMessageRequest.builder()
            .queueUrl(queueUrl).maxNumberOfMessages(1).build());
        msgResult.messages().forEach(m -> System.out.println("[SQS] Received message: " + m.body()));

        System.out.println("[OK] Floci local environment verification complete");
    }
}

Your pom.xml needs software.amazon.awssdk:aws-sdk-java-bom for version management. The endpointOverride(...) in the code is the critical step shared by all SDK clients—do not skip it. Floci fully supports AWS SDK v2 protocols; your production code only needs an endpoint change to run locally.


FAQ & Common Pitfalls

1. Port Already in Use on Startup

4566 is Floci's default port. If you've run LocalStack before, it might still be holding this port. Check with docker ps and stop the old container. Floci is designed as a smooth LocalStack replacement; just swap the image name.

2. Resource Isolation for Multi-Project Workflows

If multiple projects run against the same local Floci instance, leverage its multi-account isolation. When AWS_ACCESS_KEY_ID is a 12-digit number (e.g., 111111111111), Floci treats it as a unique account ID, completely isolating resources per account. Project A uses 111111111111, Project B uses 222222222222, and they won't interfere.

3. Spring Boot Integration Testing

It's highly recommended to use the official Testcontainers module io.floci:testcontainers-floci (use 1.14.0 for Testcontainers 1.x, or 2.15.0 for 2.x / Spring Boot 4.x). It automatically spins up an isolated Floci instance per test method, avoiding shared state and port conflicts:

java 复制代码
@Testcontainers
class S3IntegrationTest {
    @Container static FlociContainer floci = new FlociContainer();
    // floci.getEndpoint() / floci.getRegion() / floci.getAccessKey()... directly usable
}

Summary

This guide walked you through building a zero-cost local AWS development environment from scratch:

  1. One-click startup via Docker Compose with Floci, using <20MB RAM.
  2. Manual environment export to route CLI/SDK to localhost:4566.
  3. Java SDK example demonstrating S3 + DynamoDB + SQS synergy, where endpointOverride is the only core change.
  4. Mastered three practical tips: persistence mode selection, multi-account isolation, and Testcontainers integration.

You can use this setup for offline debugging, local CI validation, or learning AWS service API behavior. With over 27k stars on GitHub, floci-io/floci is fully MIT-licensed with zero paywalls or token requirements.

Next Steps: Open http://localhost:4566/_floci/ui to explore the Web Console, try local resource orchestration with Terraform, or migrate your Spring Boot integration tests from Mocks to Testcontainers + Floci to experience the confidence boost of real API testing. If you have local AWS development experiences to share, feel free to discuss them!

Last Updated:

Comments (0)

Post Comment

Loading...
0/500

No comments yet, be the first to comment!