Skip to content

Docker Compose Configuration

Most users configure floci-az entirely through environment variables — no config files needed. Every floci-az.* setting maps to a FLOCI_AZ_* env var (replace . with _, uppercase).


Common Scenarios

Storage only (no Functions)

The simplest setup — skips the Docker socket mount entirely:

services:
  floci-az:
    image: floci/floci-az:latest
    ports:
      - "4577:4577"
    environment:
      FLOCI_AZ_SERVICES_FUNCTIONS_ENABLED: "false"

All services (default)

services:
  floci-az:
    image: floci/floci-az:latest
    ports:
      - "4577:4577"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock  # required for Azure Functions

With persistent storage

Data survives container restarts. Mount a local directory and set a storage mode:

services:
  floci-az:
    image: floci/floci-az:latest
    ports:
      - "4577:4577"
    volumes:
      - ./data:/app/data
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      FLOCI_AZ_STORAGE_MODE: hybrid        # in-memory + async flush every 5 s (recommended)
      # FLOCI_AZ_STORAGE_MODE: wal         # every write goes to disk before responding
      # FLOCI_AZ_STORAGE_MODE: persistent  # flush only on graceful shutdown

With Azure SQL Database

SQL defaults to control-plane-only mode and needs no Docker socket. To opt into managed SQL Server containers, set the provider to managed, accept the EULA, and mount the Docker socket:

services:
  floci-az:
    image: floci/floci-az:latest
    ports:
      - "4577:4577"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      FLOCI_AZ_SERVICES_SQL_DATA_PLANE_PROVIDER: managed
      FLOCI_AZ_SERVICES_SQL_ACCEPT_EULA: "Y"   # accept the Microsoft SQL Server EULA
      # FLOCI_AZ_SERVICES_SQL_IMAGE: "mcr.microsoft.com/mssql/server:2025-latest"

SQL Server containers bind a random host port directly via Docker — do not add those ports to the floci-az service's ports: block. Use the /connect endpoint to discover the port.

CI / Ephemeral — maximum speed

Pure in-memory, no socket required, fastest startup:

services:
  floci-az:
    image: floci/floci-az:latest
    ports:
      - "4577:4577"
    environment:
      FLOCI_AZ_STORAGE_MODE: memory
      FLOCI_AZ_SERVICES_FUNCTIONS_ENABLED: "false"

Selective services

Disable services you don't use:

services:
  floci-az:
    image: floci/floci-az:latest
    ports:
      - "4577:4577"
    environment:
      FLOCI_AZ_SERVICES_BLOB_ENABLED: "true"
      FLOCI_AZ_SERVICES_QUEUE_ENABLED: "true"
      FLOCI_AZ_SERVICES_TABLE_ENABLED: "false"
      FLOCI_AZ_SERVICES_FUNCTIONS_ENABLED: "false"
      FLOCI_AZ_SERVICES_APP_CONFIG_ENABLED: "false"

Per-service storage override

Run most services in-memory, but use WAL for blob durability:

services:
  floci-az:
    image: floci/floci-az:latest
    ports:
      - "4577:4577"
    volumes:
      - ./data:/app/data
    environment:
      FLOCI_AZ_STORAGE_MODE: memory
      FLOCI_AZ_STORAGE_SERVICES_BLOB_MODE: wal

With Docker-backed engines (Cosmos MongoDB, Event Hubs…)

Docker-backed engines (Cosmos MongoDB/PostgreSQL/Cassandra/Gremlin) and Event Hubs sidecars (Artemis, Redpanda) are launched as sibling containers by floci-az via the Docker socket. They bind their ports directly on the host — do not publish those ports on the floci-az service:

services:
  floci-az:
    image: floci/floci-az:latest
    ports:
      - "4577:4577"
      - "4578:4578"   # Cosmos DB — Java SDK (HTTPS)
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      # Cosmos engines
      FLOCI_AZ_SERVICES_COSMOS_ENGINES_MONGODB_ENABLED: "true"
      FLOCI_AZ_SERVICES_COSMOS_ENGINES_POSTGRESQL_ENABLED: "true"
      # Event Hubs
      FLOCI_AZ_SERVICES_EVENT_HUB_ENABLED: "true"

Once the sidecars start, their ports are available on the host: localhost:27017 (MongoDB), localhost:5432 (PostgreSQL), localhost:5672 (AMQP / Artemis).

Multi-container (your app + floci-az)

When your application also runs in Docker, use the service name as the hostname:

services:
  floci-az:
    image: floci/floci-az:latest
    ports:
      - "4577:4577"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    networks:
      - app-net

  my-app:
    image: my-app:latest
    environment:
      AZURE_STORAGE_CONNECTION_STRING: >-
        DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;
        AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMh0==;
        BlobEndpoint=http://floci-az:4577/devstoreaccount1;
        QueueEndpoint=http://floci-az:4577/devstoreaccount1-queue;
        TableEndpoint=http://floci-az:4577/devstoreaccount1-table;
      # App Configuration — https:// required by the SDK; use ForceHttp transport in your client
      AZURE_APPCONFIG_ENDPOINT: https://floci-az:4577/devstoreaccount1-appconfig
    depends_on:
      - floci-az
    networks:
      - app-net

networks:
  app-net:

Environment Variable Reference

All variables are optional; the default applies when unset.

Core

Variable Default Description
FLOCI_AZ_PORT 4577 Port the emulator listens on
FLOCI_AZ_BASE_URL http://localhost:4577 Base URL embedded in API responses
FLOCI_AZ_HOSTNAME (unset) Override the hostname in SAS and invoke URLs (useful behind a reverse proxy)
FLOCI_AZ_AUTH_MODE dev dev — accept any credentials; strict — validate HMAC-SHA256 signatures

Storage

Variable Default Description
FLOCI_AZ_STORAGE_MODE memory Global storage backend: memory · persistent · hybrid · wal
FLOCI_AZ_STORAGE_PERSISTENT_PATH /app/data Container-side directory for persisted state
FLOCI_AZ_STORAGE_HOST_PERSISTENT_PATH (same as above) Host-side path when running Docker-in-Docker
FLOCI_AZ_STORAGE_WAL_COMPACTION_INTERVAL_MS 30000 How often the WAL is compacted (ms)
FLOCI_AZ_STORAGE_HYBRID_FLUSH_INTERVAL_MS 5000 How often hybrid mode flushes to disk (ms)

Per-service storage overrides

Variable Default Description
FLOCI_AZ_STORAGE_SERVICES_BLOB_MODE (global) Storage mode for Blob Storage only
FLOCI_AZ_STORAGE_SERVICES_QUEUE_MODE (global) Storage mode for Queue Storage only
FLOCI_AZ_STORAGE_SERVICES_TABLE_MODE (global) Storage mode for Table Storage only
FLOCI_AZ_STORAGE_SERVICES_APP_CONFIG_MODE (global) Storage mode for App Configuration only

Enable / disable services

Variable Default Description
FLOCI_AZ_SERVICES_BLOB_ENABLED true Enable or disable Blob Storage
FLOCI_AZ_SERVICES_QUEUE_ENABLED true Enable or disable Queue Storage
FLOCI_AZ_SERVICES_TABLE_ENABLED true Enable or disable Table Storage
FLOCI_AZ_SERVICES_FUNCTIONS_ENABLED true Enable or disable Azure Functions
FLOCI_AZ_SERVICES_APP_CONFIG_ENABLED true Enable or disable App Configuration
FLOCI_AZ_SERVICES_COSMOS_ENABLED true Enable or disable Cosmos DB (SQL API)
FLOCI_AZ_SERVICES_KEY_VAULT_ENABLED true Enable or disable Key Vault
FLOCI_AZ_SERVICES_EVENT_HUB_ENABLED true Enable or disable Event Hubs
FLOCI_AZ_SERVICES_SQL_ENABLED true Enable or disable Azure SQL Database

Azure SQL Database

Variable Default Description
FLOCI_AZ_SERVICES_SQL_DATA_PLANE_PROVIDER none none for ARM state only; managed for a real SQL Server container; external is reserved
FLOCI_AZ_SERVICES_SQL_MOCKED (unset) Deprecated provider alias: true = none, false = managed
FLOCI_AZ_SERVICES_SQL_ACCEPT_EULA N Set to Y to accept the Microsoft SQL Server EULA (managed mode only)
FLOCI_AZ_SERVICES_SQL_IMAGE mcr.microsoft.com/mssql/server:2025-latest Docker image for SQL Server containers
FLOCI_AZ_SERVICES_SQL_STARTUP_TIMEOUT_SECONDS 60 Seconds to wait for SQL Server to become ready

Azure Functions

Variable Default Description
FLOCI_AZ_SERVICES_FUNCTIONS_EPHEMERAL false true — fresh container per invocation; false — reuse warm containers
FLOCI_AZ_SERVICES_FUNCTIONS_CONTAINER_IDLE_TIMEOUT_SECONDS 300 Evict warm containers idle longer than this; 0 disables eviction
FLOCI_AZ_SERVICES_FUNCTIONS_CODE_PATH ~/.floci-az/functions Where extracted function code is stored on the host
FLOCI_AZ_SERVICES_FUNCTIONS_DOCKER_HOST_OVERRIDE (unset) Override the hostname function containers use to reach floci-az

Docker daemon

Variable Default Description
FLOCI_AZ_DOCKER_DOCKER_HOST unix:///var/run/docker.sock Docker daemon socket — unix socket or tcp://host:port
FLOCI_AZ_DOCKER_ENDPOINT_MODE auto How sidecar containers are addressed, by floci-az and in the host/port reported to clients. auto: container name/IP and internal port when floci-az runs in a container, localhost and the published port otherwise. published: always the Docker daemon's host (from docker-host) and the published port. Use it for remote daemons such as docker-in-docker or kubedock, whose containers aren't directly reachable
FLOCI_AZ_DOCKER_LOG_MAX_SIZE 10m Max log file size per function container
FLOCI_AZ_DOCKER_LOG_MAX_FILE 3 Max rotated log files per function container
FLOCI_AZ_DOCKER_DOCKER_CONFIG_PATH (unset) Path to Docker config.json for private registry auth

Resource Identity Labels

Every container and volume floci-az creates carries the base labels floci=true, floci_emulator=floci-az and, when FLOCI_AZ_DOCKER_RESOURCE_NAMESPACE is set, floci_namespace. A container backing an emulated Azure resource also carries labels tying it back to that resource, additive to the base labels:

Label Value Purpose
io.floci az Cloud provider, for multi-cloud discovery when several Floci emulators share a host
io.floci.service e.g. postgres The Azure service the container backs
io.floci.resource-id e.g. orders-db The Azure resource name (server, cache, cluster, VM, container group, container app, namespace, function app)
io.floci.subscription the subscription id The subscription the resource belongs to
io.floci.resource-group the resource group name The resource group the resource belongs to
io.floci.location e.g. eastus The Azure location of the resource
floci_service same as io.floci.service Legacy: still written, prefer the new key

This makes docker ps --filter label=io.floci.service=postgres --filter label=io.floci.resource-id=orders-db resolve an emulated resource to its backing container directly. A label whose value is unknown is omitted rather than written empty.

Labels are written when a container is created, so they apply to containers floci-az starts after upgrading. A container that already existed keeps the labels it was created with (typically only the base labels and floci_service) until floci-az recreates it, for example when the resource is deleted and created again.

  • All six keys: Azure Cache for Redis, Azure Database for PostgreSQL, MySQL and MariaDB, Azure SQL Database, AKS, Virtual Machines, Container Instances and Container Apps.
  • No scope keys (io.floci.subscription, io.floci.resource-group, io.floci.location): Service Bus and Event Hubs namespaces and Azure Functions apps, whose data-plane APIs carry no Azure scope.
  • No io.floci.resource-id and no scope keys: the shared ACR registry, the Event Hubs Kafka (Redpanda) sidecar and the per-API Cosmos DB engine containers, which are singletons with no single resource behind them.

io.floci, io.floci.service and io.floci.resource-id follow the keys floci-aws uses, so a host running both emulators can filter their containers the same way; each emulator adds its own scope keys (io.floci.account and io.floci.region there, the subscription, resource group and location keys here). floci-gcp and floci-oci do not write these keys yet.


Docker Socket Access

The Docker socket mount (/var/run/docker.sock) is required for Azure Functions. The container entrypoint automatically detects the socket's group ID at runtime and adjusts permissions — this works on both Docker Desktop (macOS/Windows) and native Linux Docker with no manual configuration.

If you don't need Functions, omit the socket mount and set FLOCI_AZ_SERVICES_FUNCTIONS_ENABLED=false.


Health Check

floci-az exposes a health endpoint you can use in depends_on conditions:

services:
  floci-az:
    image: floci/floci-az:latest
    ports:
      - "4577:4577"
    healthcheck:
      test: ["CMD", "wget", "-qO-", "http://localhost:4577/health"]
      interval: 5s
      timeout: 3s
      retries: 5

  my-app:
    depends_on:
      floci-az:
        condition: service_healthy