Skip to content

Migrate from LocalStack

Floci is a drop-in replacement for LocalStack Community. The wire protocol, port, credentials, and SDK configuration are identical, so most migrations require only an image swap. This page documents every change and provides a compatibility mode for projects that need a gentler transition.

Compatibility mode

LocalStack environment variable translation is on by default. Floci automatically maps LocalStack variables to their Floci equivalents at startup, so you can keep your existing environment variables unchanged:

docker-compose.yml
services:
  floci:
    image: floci/floci:latest
    ports:
      - "4566:4566"
    environment:
      # These LocalStack vars are automatically translated — no extra config needed:
      PERSISTENCE: "1"                      # → FLOCI_STORAGE_MODE=persistent
      LOCALSTACK_HOST: floci                # → FLOCI_HOSTNAME=floci
      LAMBDA_DOCKER_NETWORK: mynet          # → FLOCI_SERVICES_LAMBDA_DOCKER_NETWORK=mynet
      LAMBDA_REMOVE_CONTAINERS: "1"         # → FLOCI_SERVICES_LAMBDA_EPHEMERAL=true
      DEBUG: "1"                            # → QUARKUS_LOG_LEVEL=DEBUG

Explicitly set Floci variables always win — the translation only fills in values that haven't been set. To disable the translation entirely, set LOCALSTACK_PARITY=false.

Step-by-step migration

1 — Change the image

Pick the variant that matches your needs:

docker-compose.yml
# Before
image: localstack/localstack

# After — no init scripts, or init scripts that don't call aws / boto3
image: floci/floci:latest

# After — init scripts that use aws CLI or boto3 (AWS CLI + Python 3 + boto3 pre-installed)
image: floci/floci:latest-compat

To pin a specific release, replace latest / latest-compat with a version tag:

image: floci/floci:1.5.11
image: floci/floci:1.5.11-compat

The port (4566), credentials (test / test), and AWS SDK configuration are unchanged.

2 — Map environment variables

LocalStack variable Floci equivalent Notes
LOCALSTACK_HOST FLOCI_HOSTNAME Hostname embedded in response URLs
LOCALSTACK_HOSTNAME FLOCI_HOSTNAME Alias — same effect
PERSISTENCE=1 FLOCI_STORAGE_MODE=persistent Enable disk persistence
EDGE_PORT FLOCI_PORT Bind port override
GATEWAY_LISTEN QUARKUS_HTTP_HOST Bind address override
LS_LOG / DEBUG=1 QUARKUS_LOG_LEVEL Log verbosity
LAMBDA_DOCKER_NETWORK FLOCI_SERVICES_LAMBDA_DOCKER_NETWORK Network for Lambda containers
DOCKER_NETWORK FLOCI_SERVICES_DOCKER_NETWORK Network for all spawned containers
LAMBDA_REMOVE_CONTAINERS=1 FLOCI_SERVICES_LAMBDA_EPHEMERAL=true Remove Lambda containers after invocation
SERVICES (not needed) Floci starts all 41 services instantly; no selection required
LAMBDA_EXECUTOR (not needed) Floci always runs Lambda in Docker containers

3 — Init scripts (no change required)

LocalStack init scripts mounted under /etc/localstack/init/ run unchanged in Floci:

docker-compose.yml
volumes:
  - ./init/ready.d:/etc/localstack/init/ready.d:ro  # works as-is

Floci reads both /etc/localstack/init/ (compat) and /etc/floci/init/ (native). When the same filename exists in both, the Floci copy takes priority.

To use native Floci paths going forward:

docker-compose.yml
volumes:
  - ./init/ready.d:/etc/floci/init/ready.d:ro

See Initialization Hooks for the full four-phase lifecycle (boot, start, ready, stop) and script type details (.sh, .py).

4 — Init script tooling (compat image)

If your init scripts call aws or boto3, switch from localstack/localstack to floci/floci:latest-compat:

docker-compose.yml
# Before
image: localstack/localstack

# After (includes Python 3, AWS CLI, boto3 — pre-configured for localhost:4566)
image: floci/floci:latest-compat

The compat image pre-configures the AWS CLI to talk to http://localhost:4566 — no --endpoint-url flag is needed in scripts:

#!/bin/sh
aws sqs create-queue --queue-name orders    # no --endpoint-url needed
aws s3 mb s3://assets

5 — Health and status endpoints

Floci serves the LocalStack-compatible status endpoint at both paths:

GET /_localstack/init   # LocalStack compat path — still works
GET /_floci/init        # native path

If you wait on /_localstack/init or /_localstack/health in CI or scripts, no change is needed.

6 — Inspection endpoints

Endpoint Notes
GET /_aws/ses Captured emails — identical
GET /_aws/ses?id=<id> Single message — identical
DELETE /_aws/ses Clear mailbox — identical
GET /_aws/sqs/messages?QueueUrl=<url> Non-destructive queue peek — identical
DELETE /_aws/sqs/messages?QueueUrl=<url> Purge queue — identical

7 — Testcontainers

Replace the @LocalStackContainer module with the Floci module:

pom.xml
<!-- Before -->
<dependency>
  <groupId>org.testcontainers</groupId>
  <artifactId>localstack</artifactId>
  <scope>test</scope>
</dependency>

<!-- After -->
<dependency>
  <groupId>io.github.hectorvent</groupId>
  <artifactId>floci-testcontainers</artifactId>
  <version>LATEST</version>
  <scope>test</scope>
</dependency>

See the Java Testcontainers guide for full setup.

Complete before / after example

docker-compose.yml (before — LocalStack)
services:
  localstack:
    image: localstack/localstack
    ports:
      - "4566:4566"
    environment:
      LOCALSTACK_HOST: localstack
      PERSISTENCE: "1"
      LAMBDA_DOCKER_NETWORK: myapp_default
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ./data:/var/lib/localstack
      - ./init/ready.d:/etc/localstack/init/ready.d:ro
docker-compose.yml (after — Floci, minimal change)
services:
  floci:
    image: floci/floci:latest-compat  # (1)
    ports:
      - "4566:4566"
    environment:
      LOCALSTACK_HOST: floci          # translated automatically — no rename needed
      PERSISTENCE: "1"
      LAMBDA_DOCKER_NETWORK: myapp_default
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ./data:/app/data              # (2)
      - ./init/ready.d:/etc/localstack/init/ready.d:ro  # compat path — unchanged
  1. Switch to latest-compat if your init scripts use aws or boto3.
  2. LocalStack stores data in /var/lib/localstack; Floci uses /app/data.

What stays the same

  • Port 4566
  • All AWS SDK and CLI calls — no code changes
  • Dummy credentials (test / test)
  • Init scripts under /etc/localstack/init/ (compat paths)
  • /_localstack/init and /_localstack/health endpoints
  • /_aws/ses and /_aws/sqs/messages inspection endpoints
  • Docker socket mount for Lambda, RDS, and ElastiCache

Known differences

Area LocalStack Floci
Lambda executor Configurable (LAMBDA_EXECUTOR) Always Docker containers
LAMBDA_REMOTE_DOCKER Supported Not supported — use per-function S3Bucket=hot-reload instead
Service selection SERVICES=sqs,s3,... All 41 services start automatically; no selection
Data directory /var/lib/localstack /app/data
Log variable LS_LOG / DEBUG QUARKUS_LOG_LEVEL