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:
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:
# 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:
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:
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:
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:
# 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:
5 — Health and status endpoints
Floci serves the LocalStack-compatible status endpoint at both paths:
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:
<!-- 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.
See the Python Testcontainers guide.
See the Node.js Testcontainers guide.
See the Go Testcontainers guide.
Complete before / after example
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
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
- Switch to
latest-compatif your init scripts useawsorboto3. - 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/initand/_localstack/healthendpoints/_aws/sesand/_aws/sqs/messagesinspection 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 |