Skip to content

Docker & Local Dev

AutoMem provides two local development paths: Docker Compose (recommended) for a complete self-contained stack, and bare Python for lightweight API-only development against external database instances.


FeatureDocker ComposeBare Metal
Setup Time5 minutes2 minutes
External AccessLocal onlyLocal only
Data PersistenceNamed volumes (manual backup)External DB dependent
CostFreeFree
Use CaseFull-stack developmentAPI development only
Services Includedapp.py, FalkorDB, Qdrantapp.py only

Prerequisites for all local methods:

RequirementVersionPurpose
Python3.10+Runtime for app.py and background workers
GitAny recentRepository cloning

Docker Compose provides a complete, isolated stack with FalkorDB, Qdrant, and the Flask API running in containers with persistent volumes.

graph TB
    subgraph host["Host Machine"]
        Make["make dev<br/>docker-compose up"]

        subgraph docker["Docker Network<br/>automem_default"]
            API["memory-service<br/>app.py<br/>localhost:8001"]
            Falkor["falkordb<br/>localhost:6379"]
            QdrantLocal["qdrant<br/>localhost:6333"]
        end

        subgraph volumes["Docker Volumes"]
            FalkorVol["falkordb_data<br/>/var/lib/falkordb/data"]
            QdrantVol["qdrant_data<br/>/qdrant/storage"]
        end
    end

    subgraph tools["Development Tools"]
        Curl["curl<br/>localhost:8001"]
        Python["Python Scripts<br/>scripts/"]
        Tests["pytest<br/>tests/"]
    end

    Make --> API
    Make --> Falkor
    Make --> QdrantLocal

    API --> Falkor
    API --> QdrantLocal

    Falkor --> FalkorVol
    QdrantLocal --> QdrantVol

    Curl --> API
    Python --> API
    Tests --> API
  • Docker 20.10+
  • Docker Compose 2.0+

Method 1 — Makefile (recommended):

Terminal window
make dev

This runs docker compose up --build and rebuilds the Flask API image if Dockerfile or requirements.txt have changed.

Method 2 — Direct Docker Compose:

Terminal window
docker compose up --build
ServiceImage/BuildPortsPurposeHealth Check
flask-apiBuilt from Dockerfile8001AutoMem Flask API with background workersNone (depends on FalkorDB health)
falkordbfalkordb/falkordb:latest6379 (Redis), 3000 (UI)Graph database (canonical memory storage)redis-cli ping every 10s
qdrantqdrant/qdrant:v1.11.36333Vector search database (optional)None (service_started)
falkordb-browserfalkordb/falkordb-browser:latest3001Web-based graph visualizationNone (profile-gated)

Default service URLs:

  • API: http://localhost:8001
  • FalkorDB: localhost:6379 (Redis protocol)
  • FalkorDB UI: http://localhost:3000
  • Qdrant: http://localhost:6333
  • FalkorDB Browser: http://localhost:3001

Docker Compose defines named volumes for persistent data and a bind mount for source code hot-reload:

VolumeContainer PathPurposePersistence Level
falkordb_data/dataRDB snapshots + AOF (append-only file)High (every 60s or 1 key change)
qdrant_data/qdrant/storageVector collections + write-ahead logHigh (write-ahead log)
fastembed_models/root/.config/automem/modelsDownloaded ONNX embedding modelsMedium (cache, re-downloadable)
. (bind mount)/appSource code for hot-reloadN/A (host filesystem)
./backups/falkordb/backupsManual RDB exportsN/A (host filesystem)
./backups/qdrant/backupsManual snapshot exportsN/A (host filesystem)

FalkorDB persistence settings (REDIS_ARGS in docker-compose.yml):

  • --save 60 1 — Create RDB snapshot every 60 seconds if at least 1 key changed
  • --appendonly yes — Enable AOF for durability
  • --appendfsync everysec — Sync AOF to disk every second
  • --dir /data — Store persistence files in the mounted volume

Required variables for the Docker Compose stack:

VariableDocker Compose DefaultPurposeNotes
PORT8001Flask API portMust match container port mapping
AUTOMEM_API_TOKEN${AUTOMEM_API_TOKEN:-test-token}Client authenticationSet via shell or .env
ADMIN_API_TOKEN${ADMIN_API_TOKEN:-test-admin-token}Admin endpoint authenticationSet via shell or .env
FALKORDB_HOSTfalkordbFalkorDB service nameDocker internal DNS resolution
FALKORDB_PORT6379FalkorDB portStandard Redis port

Optional variables with defaults:

VariableDocker Compose DefaultPurposeNotes
FLASK_ENVdevelopmentFlask environment modeEnables debug mode, hot-reload
FLASK_DEBUG"1"Flask debug flagEnables detailed error pages
FALKORDB_PASSWORD${FALKORDB_PASSWORD:-}FalkorDB authenticationEmpty by default (no auth)
QDRANT_URLhttp://qdrant:6333Qdrant endpointDocker internal URL
QDRANT_API_KEY${QDRANT_API_KEY:-}Qdrant authenticationNot required for local Qdrant
OPENAI_API_KEY${OPENAI_API_KEY:-}OpenAI API accessFalls back to placeholder embeddings
EMBEDDING_PROVIDER${EMBEDDING_PROVIDER:-auto}Provider selectionauto|openai|voyage|local|placeholder
AUTOMEM_MODELS_DIR/root/.config/automem/modelsFastEmbed model cacheMust match volume mount path

Environment variable resolution order inside Docker Compose:

  1. Process environmentexport OPENAI_API_KEY=sk-... before running docker compose up
  2. .env file — Create .env in project root with OPENAI_API_KEY=sk-...
  3. Docker Compose defaults — Fallback values in docker-compose.yml

Docker Compose manages startup order using depends_on conditions:

  • FalkorDB has an active health check (redis-cli ping every 10s, 5 retries)
  • Flask API waits for condition: service_healthy on FalkorDB — it will not start until FalkorDB is accepting connections
  • Qdrant uses condition: service_started — the Flask API starts as soon as the Qdrant container starts and handles connection failures gracefully
Container PortHost PortServiceProtocolPurpose
80018001flask-apiHTTPAutoMem REST API
63796379falkordbTCP (Redis)FalkorDB graph queries
30003000falkordbHTTPFalkorDB built-in web UI
63336333qdrantHTTPQdrant vector search API
30013001falkordb-browserHTTPFalkorDB Browser (optional)

Flask API connects to dependencies using service names (FALKORDB_HOST=falkordb, QDRANT_URL=http://qdrant:6333). Docker Compose automatically creates DNS entries for each service name on the automem_default bridge network.

Makefile commands reference:

CommandUnderlying ActionPurposeData Loss Risk
make devdocker compose up --buildStart all services, rebuild images if Dockerfile changedNone
make logsdocker compose logs -f flask-apiFollow Flask API logs in real-timeNone
make test-integrationStart services, run pytest, keep runningRun full test suite against local Docker stackNone (uses test tokens)
make cleandocker compose down -vStop containers, remove volumesHigh — deletes all memory data
make stopdocker compose downStop containers, preserve volumesNone

Hot-reload during development:

The Flask API container mounts the project directory as a volume with FLASK_DEBUG=1. Edit any Python file and the API automatically reloads within ~2 seconds — no need to restart containers.

Running integration tests:

make test-integration orchestrates a full test run:

  1. Starts Docker Compose with test tokens (AUTOMEM_API_TOKEN=test-token, ADMIN_API_TOKEN=test-admin-token)
  2. Waits 5 seconds for service initialization
  3. Runs pytest with AUTOMEM_RUN_INTEGRATION_TESTS=1
  4. Leaves services running for debugging

Direct execution of app.py without containerization. Requires external database instances.

  • External FalkorDB instance on port 6379
  • Optional: External Qdrant instance on port 6333
  • Python 3.10+ virtual environment

Step 1 — Create virtual environment and install dependencies:

Terminal window
git clone https://github.com/verygoodplugins/automem.git
cd automem
python -m venv venv
source venv/bin/activate
pip install -r requirements.txt

Step 2 — Configure environment:

Create .env in project root or export variables:

Terminal window
FALKORDB_HOST=localhost
FALKORDB_PORT=6379
AUTOMEM_API_TOKEN=your-dev-token
ADMIN_API_TOKEN=your-admin-token
PORT=8001
# Optional: enable vector search
QDRANT_URL=http://localhost:6333
# Optional: enable real embeddings
OPENAI_API_KEY=sk-...

Step 3 — Run the application:

Terminal window
python app.py

Expected startup output:

[INFO] Loading configuration...
[INFO] Connecting to FalkorDB at localhost:6379
[INFO] FalkorDB connected successfully
[INFO] Starting enrichment worker thread
[INFO] Starting embedding worker thread
[INFO] Starting consolidation scheduler
* Running on http://[::]:8001

The server binds to [::] (IPv6 dual-stack) on port 8001.


After starting either method, verify AutoMem is operational:

Terminal window
curl http://localhost:8001/health

Expected response (healthy):

{
"status": "healthy",
"falkordb": "connected",
"qdrant": "connected",
"memory_count": 0,
"enrichment": {
"status": "running",
"queue_depth": 0
},
"graph": "memories"
}

Response fields:

FieldTypeDescription
statusstringOverall health: "healthy" or "unhealthy"
falkordbstringFalkorDB connection: "connected" or error message
qdrantstringQdrant connection: "connected", "unavailable", or "not configured"
memory_countintegerTotal memories in graph
enrichment.statusstringWorker thread state: "running" or "stopped"
enrichment.queue_depthintegerPending enrichment jobs
graphstringFalkorDB graph name (default: memories)
ProblemCauseSolution
503 Service UnavailableFalkorDB not runningdocker compose up -d falkordb
503 Service UnavailableIncorrect FALKORDB_HOSTRailway uses .railway.internal; Docker uses falkordb
503 Service UnavailableWrong FALKORDB_PORTDefault is 6379
503 Service UnavailableAuth failureCheck FALKORDB_PASSWORD matches both services

After the health check passes, store and retrieve a test memory:

Terminal window
# Store a memory
curl -X POST http://localhost:8001/memory \
-H "Authorization: Bearer test-token" \
-H "Content-Type: application/json" \
-d '{"content": "Prefer PostgreSQL for relational data", "type": "Preference"}'
# Recall memories
curl "http://localhost:8001/recall?q=database+preferences" \
-H "Authorization: Bearer test-token"

Successful response indicators:

  • POST returns 201 Created with memory_id
  • GET /recall returns non-empty results array
  • Memory appears with match_type: "vector" or "keyword"

Docker Compose is optimized for development. Production deployments require additional hardening:

AspectDocker Compose (Dev)Production Recommendations
Debug ModeFLASK_DEBUG=1, verbose loggingDisable debug, set LOG_LEVEL=INFO or WARNING
API TokensDefaults to test-token, test-admin-tokenGenerate cryptographically secure tokens (32+ chars)
Port ExposureAll ports mapped to localhostUse reverse proxy (nginx, Traefik); expose only necessary ports
Volume BackupsManual exports to ./backups/Automated backups to S3/remote storage
Resource LimitsUnlimitedSet deploy.resources.limits in docker-compose.yml
Restart Policyrestart: unless-stoppedUse restart: always with health checks
SSL/TLSHTTP onlyTerminate SSL at reverse proxy or use Traefik
MonitoringDocker logsExternal monitoring (Prometheus, health checks)

When to use Docker Compose vs. Railway:

ScenarioRecommended Deployment
Single developer, local-only accessDocker Compose on local machine
Team collaboration, remote access neededRailway
Self-hosted production, existing infrastructureDocker Compose with reverse proxy + backups
Prototyping, short-term experimentsDocker Compose (no cloud costs)
Production with minimal ops overheadRailway (managed backups, monitoring)
Air-gapped environments, strict data localityDocker Compose on self-hosted infrastructure

Data can be migrated using backup/restore scripts:

  1. Export from Docker Compose:

    Terminal window
    # Export FalkorDB RDB
    docker compose exec falkordb redis-cli SAVE
    docker compose cp falkordb:/data/dump.rdb ./backups/falkordb/
    # Export Qdrant snapshot
    curl -X POST http://localhost:6333/collections/memories/snapshots
  2. Import to Railway:

    Use the GitHub Actions backup workflow to populate Railway from exported snapshots.